Blog Archives

Exceptions (part 3, advanced)

For Windows Forms and WPF we have specific exceptions to deal with. Actually these are not really exceptions. They are events, which are raised whenever any unhandled exception occurs. “Unhandled” means there is nothing that catches exceptions and the entire stack did not come up with any solution. Nothing stopped the thread falling down to its lowest level, and even that level does not know what to do with the exception. You can eg. throw an exception on a button click to cause this behavior.
These events allow applications to log information about unhandled exceptions.

In Windows Forms the EventHandler is defined in System.Threading and is called ThreadExceptionEventHandler. If you do not define this event call then your application will crash when unhandled exceptions show up.

[STAThread]
static void Main() {
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.ThreadException += Application_ThreadException;
    Application.Run(new Form1());
} //

static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e) {
    Exception lException = (Exception)e.Exception;
    MessageBox.Show(lException.Message);
} //

The approach in WPF is similar. We are talking in Domains. Therefore we subscribe to AppDomain.CurrentDomain.UnhandledException .

public MainWindow() {
    InitializeComponent();
    AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;            
} //

void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
    Exception lException = (Exception)e.ExceptionObject;
    MessageBox.Show(lException.Message + "\nIsTerminating: " + e.IsTerminating);
} //

private void button1_Click(object sender, RoutedEventArgs e) {
    throw new Exception("user exception thrown");
} //
Advertisements

Exceptions (part 2, advanced)

Season’s Greetings!
Today we have a very short post about custom exceptions, which provide more specific information. Of course the custom exception has to inherit from System.Exception. Adding several constructors including a parameterless one is good practice.
The suffix “Exception” in your exception name is convention (eg. “OutOfMemory
Exception
“, “FileNotFoundException“). Adding the Serializable attribute can be useful when you work across application domains. Properties help providing extra information.

Don’t use the System.ApplicationException class.
http://msdn.microsoft.com/en-us/library/system.applicationexception.aspx states:

If you are designing an application that needs to create its own exceptions, you should derive custom exceptions from the Exception class. It was originally thought that custom exceptions should derive from the ApplicationException class; however in practice this has not been found to add significant value.

In other words: ApplicationException is a relic of the past, where Microsoft intended developers to inherit all their custom exceptions from. But this has never become practice and custom exceptions now derive from the Exception class.

[Serializable]
public class UserNotFoundException : Exception {
    public string UserId { get; private set; }
            
    public UserNotFoundException(string xUserId) : base() {
        UserId = xUserId;
        base.HelpLink = "http://www.ohta.de";
    } // constructor

    public UserNotFoundException(string xUserId, string xMessage)
        : base(xMessage) {
        UserId = xUserId;
        base.HelpLink = "http://www.ohta.de";
    } // constructor

    public UserNotFoundException(string xUserId, string xMessage, Exception xInnerException)
        : base(xMessage, xInnerException) {
        UserId = xUserId;
        base.HelpLink = "http://www.ohta.de";
    } // constructor

    protected UserNotFoundException(SerializationInfo xSerializationInfo, StreamingContext xStreamingContext) {
        UserId = xSerializationInfo.GetValue("UserId", typeof(string)) as string;
    } // constructor

    public void GetObjectData(SerializationInfo xSerializationInfo, StreamingContext xStreamingContext) {
        xSerializationInfo.AddValue("UserId", UserId, typeof(string));
    }
} // class

Exceptions (part 1, advanced)

Exceptions are not errors, they are exceptions. They should not be used for code that can deal with errors. Exceptions are for situations that cannot be solved like running out of RAM or hard disk space. They are pretty slow, because they deal with the entire stack trace. Here is a short benchmark program:

static double DoSomeCalc(double d) {
    return d * 1.1;
} //
static double DoSomeCalc2(Exception e) {
    throw e;
} //

static void Exceptions1() {
    const int n = 10000000;
    double d = 1.0;

    Stopwatch lStopwatch = new Stopwatch();
    lStopwatch.Start();

    for (int i = 0; i < n; i++) d *= 1.1;
    Console.WriteLine("benchmark ms " + lStopwatch.ElapsedMilliseconds);

    lStopwatch.Restart();
    try { for (int i = 0; i < n; i++)  d *= 1.1; }
    catch (Exception) { throw; }
    Console.WriteLine("efficient try/catch block ms " + lStopwatch.ElapsedMilliseconds);

    lStopwatch.Restart();
    for (int i = 0; i < n; i++) {
        try { d *= 1.1; }
        catch (Exception) { throw; }
    }
    Console.WriteLine("inefficient try/catch block ms " + lStopwatch.ElapsedMilliseconds);
    Console.WriteLine();

    lStopwatch.Restart();
    for (int i = 0; i < n; i++) d = DoSomeCalc(d);
    Console.WriteLine("method call, benchmark ms " + lStopwatch.ElapsedMilliseconds);

    lStopwatch.Restart();
    try { for (int i = 0; i < n; i++)  d = DoSomeCalc(d); }
    catch (Exception) { throw; }
    Console.WriteLine("method call, efficient try/catch block ms " + lStopwatch.ElapsedMilliseconds);

    lStopwatch.Restart();
    for (int i = 0; i < n; i++) {
        try { d = DoSomeCalc(d); }
        catch (Exception) { throw; }
    }
    Console.WriteLine("method call, inefficient try/catch block ms " + lStopwatch.ElapsedMilliseconds);
    Console.WriteLine();

    Exception e = new Exception();  // only one instance, we exclude the creation time for the object in this test
    lStopwatch.Restart();
    for (int i = 0; i < 100; i++) {
        try { throw e; }
        catch (Exception) { }
    }
    Console.WriteLine("100 exceptions thrown in ms " + lStopwatch.ElapsedMilliseconds);

    lStopwatch.Restart();
    for (int i = 0; i < 100; i++) {
        try { DoSomeCalc2(e); }
        catch (Exception) { }
    }
    Console.WriteLine("method call, 100 exceptions thrown in ms " + lStopwatch.ElapsedMilliseconds);

    lStopwatch.Stop();
    Console.ReadLine();
} //

example output:
benchmark ms 2227
efficient try/catch block ms 2179
inefficient try/catch block ms 2201

method call, benchmark ms 2448
method call, efficient try/catch block ms 2436
method call, inefficient try/catch block ms 2431

100 exceptions thrown in ms 603
method call, 100 exceptions thrown in ms 652

The first three results are in line with each other. The code optimizer does the job and there is no visible impact on the outcome. The difference is more likely to be a result of context switching (threading).
And when we call a method the slowdown is also regular, no big impact of the try/catch blog.
But when exceptions are thrown, the system considerably slows down. 600 ms for just 100 exceptions is a disaster. And it gets even worse when you call a method, because the stack trace becomes longer. Imagine what happens when you have nested methods involved.

The conclusion is that throwing exceptions for the programmer’s convenience is bad practice. Exceptions must be avoided by all means. You’d rather perform a quick zero check than raise a DivideByZeroException.

Do not reuse exception objects, this is not thread safe. In general try to avoid re-throwing exceptions. Anyway, let’s see how to re-throw exceptions in case you need it:

a) Re-“throw” without any identifier. This preserves the original exception details.

static void Exceptions2() {
    int lZero = 0;
    try { int i = 4 / lZero; }
    catch (Exception) { throw; }
} //

static void Exceptions3() {
    try { Exceptions2(); }
    catch (Exception e) {
        Console.WriteLine("Message:        {0}", e.Message);
        Console.WriteLine("StackTrace:     {0}", e.StackTrace);
        Console.WriteLine("HelpLink:       {0}", e.HelpLink);
        Console.WriteLine("InnerException: {0}", e.InnerException);
        Console.WriteLine("TargetSite:     {0}", e.TargetSite);
        Console.WriteLine("Source:         {0}", e.Source);
    }
} //

Message: Attempted to divide by zero.
StackTrace: at ConsoleApplication1.Program.Exceptions2() in ….\Program.cs:line 1155
at ConsoleApplication1.Program.Exceptions3() in ….\Program.cs:line 1160
HelpLink:
InnerException:
TargetSite: Void Exceptions2()
Source: ConsoleApplication1

b) Re-throw the original exception. Add some more information.

static void Exceptions4() {
    int lZero = 0;
    try { int i = 4 / lZero; }
    catch (DivideByZeroException e) { throw new DivideByZeroException("Division by Zero", e); }
    catch (Exception e) { throw new Exception("Any Exception", e); } // will not be thrown in this example
} //

static void Exceptions5() {
    try { Exceptions4(); }
    catch (Exception e) {
        Console.WriteLine("Message:        {0}", e.Message);
        Console.WriteLine("StackTrace:     {0}", e.StackTrace);
        Console.WriteLine("HelpLink:       {0}", e.HelpLink);
        Console.WriteLine("InnerException: {0}", e.InnerException);
        Console.WriteLine("TargetSite:     {0}", e.TargetSite);
        Console.WriteLine("Source:         {0}", e.Source);
    }
} //

example output:
Message: Division by Zero
StackTrace: at ConsoleApplication1.Program.Exceptions4() in ….\Program.cs:line 1134
at ConsoleApplication1.Program.Exceptions5() in ….\Program.cs:line 1140
HelpLink:
InnerException: System.DivideByZeroException: Attempted to divide by zero.
at ConsoleApplication1.Program.Exceptions4() in ….\Program.cs:line 1133
TargetSite: Void Exceptions4()
Source: ConsoleApplication1

Basic Thread

static private void myThread() {
  Thread.Sleep(2000);
  Console.WriteLine("hello world!");
} //

static void Main(string[] args) {
  Thread t = new Thread(new ThreadStart(myThread));
  t.IsBackground = true;
  t.Name = "MyBackgroundThread";
  t.Priority = ThreadPriority.Normal;
  Console.WriteLine("starting new thread");
  t.Start();

  Console.WriteLine("waiting for started thread to finish");
  t.Join();
  Console.WriteLine("press return to exit the program");
  Console.ReadLine();
} //

Nearly all PCs these days have multiple cores and/or CPUs. There is a speed benefit using them simultaneously. Windows can run applications independently. You can eg. run Notpad and Paint in parallel. Each application runs as a process. And each process can have many threads. A thread is more or less some code that is executed for a certain time period. Windows decides on its own when to pause a thread and switch to another thread. This is called context switching.

To run a simple thread we need the “System.Threading” namespace. You declare it with “using System.Threading;”.

The output console is a static and thread safe class. You neither have to instantiate the class nor synchronise the output. This is quite helpful, otherwise the example program would have to be a bit more complex. You would not be able to get access to the console from two different threads without risking deadlocks.

It is good practice to define the thread priority. That way Windows knows how important your code is and how much time it should assign for its execution. In a stock trading system you would eg. assign a high priority to the trade decision thread and a low priority to any screen output.

The join method is called on the main thread to let it wait until our newly generated thread terminates. You cannot restart a thread once it has terminated. In our example we started a background thread by setting t.IsBackground to true. All background threads (and the application) automatically stop as soon as all Foreground threads have terminated. Thus Foreground threads need to handle the shut down process, otherwise the application keeps on running unintentionally.

Some threads need parameters. Have a look at the following code. It uses a class to pass two parameters to the new thread.

private class parameters {
  publicĀ  double d;
  publicĀ  string s;
}//

static private void myThread(object xParameters) {
  parameters p = xParameters as parameters;
  Console.WriteLine("your parameters are " + p.d + " " + p.s);
} //

static void Main(string[] args) {
  Thread t = new Thread(new ParameterizedThreadStart(myThread));
  t.IsBackground = true;
  t.Name = "MyBackgroundThread";
  t.Priority = ThreadPriority.Normal;
  parameters p = new parameters{d = 2.5, s = "meters"};
  t.Start(p);
  t.Join();
  Console.WriteLine("press return to exit the program");
  Console.ReadLine();
} //