WinRT vs WPF Drawing Performance

Although WPF/XAML are great for developing user interfaces it does have a reputation for being slow at drawing. Certainly it is recommended you keep the visual tree down to less than 10,000 objects if you want anything like a responsive user experience.

So how does the new WinRT compare to WPF? There is no need to wonder when we can create a couple of simple tests and see how it works in practice. My test consists of a single XAML page that contains a TextBlock and Grid. The TextBlock will be used to indicate how many frames per second are being drawn and the Grid used to host instances of the Rectangle shape class. The WPF version of the XAML is as follows.

    <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="1*"/>
            </Grid.RowDefinitions>
            <TextBlock x:Name="speed"/>
            <Grid x:Name="g" Grid.Row="1"/>
        </Grid>
    </Window>

The code behind is a little more verbose but simple enough. It creates rows and columns for the Grid and fills each cell with a Rectangle instance. It then kicks off a timer that fires as quickly as possible. The timer tick will update the Brush instances used to color the background and border of each Rectangle. By counting how many times per second the timer ticks we can see the update rate.

    public partial class MainWindow : Window
    {
        public int _count = 0;
        public Random _rand = new Random();
        public DateTime _startTime;
        public DispatcherTimer _timer = new DispatcherTimer();
        public List _shapes = new List();
        public List _brushes = new List();

        public MainWindow()
        {
            InitializeComponent();

            int bounds = 40;
            for (int i = 0; i &lt; bounds; i++)
            {
                g.RowDefinitions.Add(new RowDefinition() 
                    { Height = new GridLength(1, GridUnitType.Star) });

                g.ColumnDefinitions.Add(new ColumnDefinition 
                    { Width = new GridLength(1, GridUnitType.Star) });
            }

            for (int x = 0; x &lt; bounds; x++)
            {
                for (int y = 0; y  1000)
            {
                if (_count &gt; 0)
                    speed.Text = _count.ToString();
                else
                    speed.Text = "0";

                _count = 0;
                _startTime = DateTime.Now;
            }

            int index = _rand.Next(_brushes.Count);
            foreach (Rectangle tb in _shapes)
            {
                tb.Fill = _brushes[index++ % _brushes.Count];
                tb.Stroke = _brushes[index++ % _brushes.Count];
            }

            _count++;
        }
    }

Running on a Windows 7 machine we getting the following output…

WPF Rectangle Drawing

…which averages around the 15 frames per-second. It gives the same frame rate when run maximized or restored. Running the same test as a Metro app at full screen we get the following…

WinRT Rectangle Drawing

…which is 40 frames compared to the 15 for WPF. A nice 260% performance improvement. But applications are made up of more than simple rectangles. So with a minor change we can fill each cell with a TextBlock that has a new Text value set for each timer tick. Running this under WPF we get…

WPF Text Drawing Performance

…around 11 frames per second and the Metro app version comes out at…

WinRT Text Drawing Performance

…around 10 frames on average, the screenshot happened to be taken when it was at 9 but it averaged 10. So it seems that Text drawing performance is about the same and rectangle drawing is significantly faster under WinRT. Obviously this is only a rough and ready comparison but it is very positive to see that even at the Consumer Preview stage the WinRT implementation is at least at good and in many areas better than WPF. You have to assume that it will only get faster in the future as developer time shifts from adding features to improving performance.

Categories: WinRT, WPF Tags:

WinForms: Cross Thread Calls

April 1, 2012 1 comment

.NET Framework 1.0 / 1.1

In the beginning there was only WinForms for developing user interfaces on the desktop. As WinForms is just a wrapper layer on top of Win32 it means your .NET controls have thread affinity just like Win32 controls. So any method or property you call on a control must occur on the same thread that created the control.

Long running tasks are the bane of user interfaces. If you perform them synchronously they freeze the application and make it unresponsive until the task is completed. To avoid this we use worker threads. But with thread affinity we cannot update the user interface from the worker thread when the task has some feedback to show. Fortunately the .NET designers thought of this and provided the Control.InvokeRequired and Control.Invoke methods.

To demonstrate this we have a simple WinForms application. It consists of a Form with a button for starting a long running task and a progress bar for showing the progress of that task as it executes. The button1_Click event handler creates a thread pool work item in order to kick off the LongProcess1 method in a separate worker thread. We simulate a long running operation by placing a Thread.Sleep inside a loop and repeatedly call the ProgressUpdate1 method to update the progress bar with current state of the task.

    private void button1_Click(object sender, EventArgs e)
    {
        Console.WriteLine("button_Click Thread:{0}",
            Thread.CurrentThread.ManagedThreadId);

        ThreadPool.QueueUserWorkItem(new WaitCallback(LongProcess1), this);
    }

    private void LongProcess1(object state)
    {
        Console.WriteLine("LongProcess Thread:{0}",
            Thread.CurrentThread.ManagedThreadId);

        Form1 form = (Form1)state;

        for (int i = 0; i < 100; i+=20)
        {
            Thread.Sleep(100);
            form.ProgressUpdate1(i);
        }
    }

    private void ProgressUpdate1(int percent)
    {
        Console.WriteLine("ProgressUpdate Thread:{0} Percent:{1}",
            Thread.CurrentThread.ManagedThreadId, percent);

        if (progressBar1.InvokeRequired)
            progressBar1.BeginInvoke(new UpdateDelegate(ProgressUpdate1),
                                     new object[] {percent});
        else
            progressBar1.Value = percent;
    }

    private delegate void UpdateDelegate(int percent);

We can see inside the ProgressUpdate1 the use of the InvokeRequired property to discover if the current thread is the same as the thread the control was created on. If it returns True then you need to use either the BeginInvoke or Invoke method to request the provided delegate be executed on the thread that created the associated control.

Internally the BeginInvoke is implemented by posting a custom windows message to a hidden control that exists on the user interface thread. Win32 knows the thread associated with each control and so the message is automatically queued to the message queue of the owning thread. Once the message is dispatched the hidden controls WndProc will process it by calling the provided delegate.

Running our Form and clicking the Start button gives this…

WinForms Cross Thread Calls

…with the following console output…

WinForms Invoke/InvokeRequired

Note the area in yellow highlight that shows each update results in the ProgressUpdate1 method being called twice. The first time it is called on thread 10, the worker thread. This causes the BeginInvoke to be called and when the delegate is called be are back on thread 9, the user interface thread.

Although this technique works it has some disadvantages:-

  • The Form is passed into the worker
  • Which callback method to call is hardcoded
  • The callback method is called twice instead of once
  • InvokeRequired/BeginInvoke pattern must be used in all callback methods


.NET Framework 2.0

Most of the above problems can be solved by making use of the SynchronizationContext class that was introduced in version 2.0 of the .NET Framework. The SynchronizationContext is a base class that is used to abstract away the details of how to execute code in the correct context, in practice making sure code is executed in the correct thread.

In our case we are interested in the derived class called WinFormsSynchronizationContext. An instance of this context is created the first time any WinForms control is created within a thread and it is assigned to the thread local SynchronizationContext.Current. So although you will not see that class explicitly created if is the one in existence. You can check this yourself by stepping through the new version of the code and examining the type of the SynchronizationContext.Current value.

        private void button2_Click(object sender, EventArgs e)
        {
            Console.WriteLine("button_Click Thread:{0}",
                Thread.CurrentThread.ManagedThreadId);

            ThreadPool.QueueUserWorkItem(new WaitCallback(LongProcess2),
                                         SynchronizationContext.Current);
        }

        private void LongProcess2(object state)
        {
            Console.WriteLine("LongProcess Thread:{0}",
                Thread.CurrentThread.ManagedThreadId);

            SynchronizationContext context = (SynchronizationContext)state;

            for (int i = 0; i < 100; i+=20)
            {
                Thread.Sleep(100);
                context.Post(new SendOrPostCallback(ProgressUpdate2), i);
            }
        }

        private void ProgressUpdate2(object percent)
        {
            Console.WriteLine("ProgressUpdate Thread:{0} Percent:{1}",
                Thread.CurrentThread.ManagedThreadId, percent);

            progressBar1.Value = (int)percent;
        }

Using the Post method of the context ensures the passed in delegate is executed back on the original WinForms thread. We no longer get two calls to the callback because the callback is only ever called when already back on the correct thread. We can see this is the case in console output.

WinForms SynchronizationContext

We still have one of our disadvantages to take care of. The actual callback method is still hardcoded into the worker method. It would be better if the callback were passed into the long running method as a parameter instead of being fixed. This allows the long running code to be reused from multiple points in our WinForms application where each usage needs a different callback used.

Our updated code now looks like the following with a helper class used to pass two pieces of information into the worker method.

        public class ItemContext : Tuple>
        {
            public ItemContext(SynchronizationContext context, Action action)
                : base(context, action)
            { }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            ThreadPool.QueueUserWorkItem(
                new WaitCallback(LongProcess3),
                new ItemContext(SynchronizationContext.Current,
                                new Action((p) => progressBar1.Value = p)));
        }

        private void LongProcess3(object state)
        {
            ItemContext context = (ItemContext)state;

            for (int i = 0; i < 100; i+=20)
            {
                Thread.Sleep(100);
                context.Item2(innerI)), null);
            }
        }

We have achieved our goal of using another thread for executing an operation whilst safely returning to the WinForms thread for processing updates or results from the operation. We have also parameterized the operation with a SynchronizationContext and callback so the operation can be reused.

.NET Framework 4.5

With the introduction of the async and await keywords we can improve our code again. Instead of using the ThreadPool explicitly we can use the static Task.Run method to request an operation be executed asynchronously on another thread. This has the advantage that we can await the operation,  so the button4_Click method will continue on the original WinForms thread once the operation has completed.

So performing post-operation code becomes trivial as we just add it immediately after the await. This is easier than passing a callback into the operation. Here is an example of how we could do this without the need for a helper class as seen before.

        private async void button4_Click(object sender, EventArgs e)
        {
            var context = SynchronizationContext.Current;
            await Task.Run(() => LongProcess4(
                               (percent) => context.Post(
                                    new SendOrPostCallback(
                                        (_) => progressBar.Value = percent), null)));

            // Post-Operation code goes here...
        }

        private void LongProcess4(Action progress)
        {
            for (int i = 0; i < 100; i+=20)
            {
                Thread.Sleep(100);
                progress(i);
            }
        }

Our final version of code will use a helper method that makes it simple to solve our original problem, how to execute code on another thread and then get back to the original WinForms thread with feedback.

        private async void button_Click(object sender, EventArgs e)
        {
            await RunWithCallback(LongProcess4,
                                  (percent) => progressBar.Value = percent);
        }

        private Task RunWithCallback(Action action, Action callback)
        {
            var context = SynchronizationContext.Current;
            return Task.Run(() => action(
                                (p) => { context.Post(new SendOrPostCallback(
                                    (_) => callback(p)), null); }));
        }

You can call RunWithCallback with two parameters, a delegate to execute as the operation on the background thread and another delegate which is the callback method to be passed into the operation. With the use of lambdas it makes for very concise code for methods that would have been trivial.

WPF: Worker Thread Usage

March 10, 2012 13 comments

Most developers assume that WPF is only used for generating the UI of your application. But it also proves a great tool for generating simple reports from worker threads.  The following workflow demonstrates how easy it is…

1. XAML Design
Use your existing tools such as Visual Studio or KAXAML to create your report layout using the usual WPF controls such as Grid, StackPanel, TextBlock and so forth. If your one of the few developers that is familiar with Expression Blend then you should be able to create a nice looking report really quickly. Use data binding to get the actual values that will be needed when the report is generated.

2. Worker Thread
Use a worker thread to load in the XAML and load in the current data values from a database or other source. Set the DataContext at the root of the XAML to the object that provides your report values.

3. Render and Save
Use the RenderTargetBitmap to render the XAML to a bitmap that can then be saved in whatever format you prefer.

4. Prevent Memory Leak
After following the first three steps you will run your reports and notice that you are slowing leaking memory. Here is a minimal console application to demonstrate the leak occurring…

    static void Main(string[] args)
    {
        for (int i = 0; i &lt; 10; i++)
        {
            Thread t = new Thread(() =&gt; ThreadRun());
            t.SetApartmentState(ApartmentState.STA);
            t.Start();
            t.Join();

            Console.WriteLine("Total Memory = {0}", GC.GetTotalMemory(true));
        }

        Console.ReadLine();
    }

    static void ThreadRun()
    {
        Grid g = new Grid();
        TextBlock tb = new TextBlock();
        tb.Text = "Hello World!";
        g.Children.Add(tb);
    }

WPF Worker Thread Leak

WPF makes use of a thread specific Dispatcher instance for event handling. Even though our example has no user interaction and does not even render it still causes a dispatcher instance to be created for the thread. If you create a WPF control then you cause a dispatcher to be created if not already present.

Some WPF controls also use the dispatcher for memory management although that is not the case for the simple example we have with a Grid and TextBlock. Whenever a thread has a dispatcher you must close it down gracefully to prevent a memory leak. Here is the updated code with the dispatcher shutdown code added.

    static void ThreadRun()
    {
        Grid g = new Grid();
        TextBlock tb = new TextBlock();
        tb.Text = "Hello World!";
        g.Children.Add(tb);</code>

        // Allow dispatcher to process any waiting delegates as it shutsdown
        Dispatcher.CurrentDispatcher.BeginInvokeShutdown(DispatcherPriority.SystemIdle);
        Dispatcher.Run();
    }

Now our example runs without leaking, once it has settled down in usage from the first iteration.

WPF Worker Thread Leak Fixed

References
MSDN – Thread
MSDN – Dispatcher

Categories: WPF Tags: ,

BCL: Serialization Performance

October 18, 2011 1 comment

Almost all real world applications needs to perform some form of serialization to turn data into objects and back again. If working against a relational database that will usually entail using a framework to take care of the object mapping for you. NHibernate and the Entity Framework are the most popular choices at the moment. The time it takes to turn data into an object is usually small compared to the database query time and so the serialization mechanism is not a major performance bottleneck.

There are many instances where using a full database for the back end is overkill. In that case you need to take care of the serialization yourself and there are several choices available. To make the right choice we need to find out the performance and output sizes of the options.

Output Size
We will start by using the following trivial definition of a structure that has just a single field.


    [Serializable]
    [DataContract]
    [StructLayout(LayoutKind.Sequential)]
    public struct SmallStruct
    {
        [DataMember]
        public int i;
    }

To discover the output size when using the XmlSerializer we can use the following code. It streams outputs to a MemoryStream that itself uses an array of bytes for storage. This gives us the required metric of byte size.


    var ss = new SmallStruct();
    var xml = new XmlSerializer(typeof(SmallStruct));
    using (var ms = new MemoryStream())
    {
        xml.Serialize(ms, ss);
        Console.WriteLine("Xml Size = {0}", ms.ToArray().Length);
    }

Swapping the XmlSerializer for the BinaryFormatter, DataContractSerializer and DataContractJsonSerializer classes gives us the output size for those alternatives. Our final option for comparison is to write our own serializer that is as fast and concise as possible. This acts as a benchmark for comparing the maximum possible performance against the available implementations. My implementation uses the Marshal class to create an unmanaged copy of the structure and then copy the unmanaged bytes back to managed code as a byte array.


    var ss = new SmallStruct();
    var size = Marshal.SizeOf(ss);
    var ptr = Marshal.AllocHGlobal(size);
    byte[] bytes = new byte[size];
    Marshal.StructureToPtr(ss, ptr, true);
    Marshal.Copy(ptr, bytes, 0, size);
    Marshal.FreeHGlobal(ptr);
    Console.WriteLine("Marshal Size = {0}\n", bytes.Length);

The following table shows how many bytes are output from the various options.

Serialization Size for Single Integer

The Marshal implementation provides the minimum possible number of bytes,  an integer is four bytes and so that is the smallest possible output size. Json is a very compact format and essentially consists of name/value pairs.  With only a single value inside the structure it means an output of just a single name and value becomes very concise.

All the others are relatively large because they include information about the type that is being serialized. Hence even a trivial struct includes a overhead of at least 150 bytes. We can conclude from this that if you are dealing with a large number of small objects you are best of using Json or a custom Marshal style implementation. Otherwise be prepared for a very bloated output.

Performance
To compare performance we use a loop that times the duration of the serialize action. Note that we create the serializer instance outside of the loop and so the set-up cost of any initialization code in the constructor is not included. This is fair because we should be spending far more time persisting objects than creating the serializer instances themselves.


    var sw = new Stopwatch();
    var ss = new SmallStruct();
    var xml = new XmlSerializer(typeof(SmallStruct));
    using (var ms = new MemoryStream(500))
    {
        sw.Start();
        for (int i = 0; i < 300000; i++)
        {
            ms.Seek(0, SeekOrigin.Begin);
            xml.Serialize(ms, ss);
        }
        sw.Stop();
    }

    Console.WriteLine("Serializations per second = {0}",
        (int)((double)1000 / sw.ElapsedMilliseconds * 300000));

The code for the Marshal based implementation is a little different and caches as much set-up information as it can outside the loop.


    var sw = new Stopwatch();
    var ss = new SmallStruct();
    var size = Marshal.SizeOf(ss);
    var ptr = Marshal.AllocHGlobal(size);
    byte[] bytes = new byte[size];
    sw.Start();
    for (int i = 0; i < 300000; i++)
    {
        Marshal.StructureToPtr(ss, ptr, true);
        Marshal.Copy(ptr, bytes, 0, size);
    }
    sw.Stop();

    Marshal.FreeHGlobal(ptr);

    Console.WriteLine("Serializations per second = {0}",
        (int)((double)1000 / sw.ElapsedMilliseconds * 300000));

The following table shows how many serializations were performed per-second.

Serialization Speed for Single Integer

Again the Marshal implementation is the best and this is not surprising as it is hard to imagine performing less work per iteration than simply copying four bytes into a byte array. Of the others the XmlSerializer is a clear loser being significantly slower than any other option.

Larger Structures
Not many real world objects consist of just a single field and so we are going to run the tests again but this time using the following.


    [Serializable]
    [DataContract]
    [StructLayout(LayoutKind.Sequential)]
    public struct SmallStruct
    {
        [DataMember] public int integer1;
        [DataMember] public int integer2;
        [DataMember] public int integer3;
        [DataMember] public float floating1;
        [DataMember] public double floating2;
        [DataMember] public string firstname;

        public SmallStruct(bool x)
        {
            integer1 = 100;
            integer2 = 1000;
            integer3 = 10000;
            floating1 = 123.456F;
            floating2 = 1234.5678;
            firstname = "A typical length string";
        }
    }

Our new struct gives the following output sizes…

Serialization Size for Typical Struct

…and serializations per-second.

Serialization Speed for Typical Struct

Results
We can conclude that there is no good reason to use the XmlSerializer. It produces the most bloated output size and runs much slower than anything else. This is not terribly surprising as it the oldest of the implementations and has been around since the earliest days of the .NET Framework. The introduction of WCF brought us the DataContractSerializer which is used by WCF to convert objects into Xml for transport.

So the only real choice to be made is between using the DataControlSerializer that outputs to Xml or the Json variation. Json produces more compact output but Xml is a better known standard with better tools available for consuming it. The project requirements would likely make this decision for you. If only there was a serializer based on the Marshal style approach we would be able to get the smallest possible output size and lightning fast performance. A graph of relative performance shows just how handy that would be.

Serialization Graph

Resources
MSDN – XmlSerializer
MSDN – BinaryFormatter
MSDN – DataContractSerializer
MSDN – DataContractJsonSerializer
MSDN – Marshal Class

Categories: BCL Tags: ,

CLR: System.ValueType

September 27, 2011 1 comment

Every .NET developer knows that all types derive from the System.Object base class. But if you ask developers what the base class of a struct or enum is you will find many do not know or simply assume it is System.Object. To get the most from the CLR you should understand the type system you are using.

All value types derive either directly or indirectly from the System.ValueType class. There are only two ways to create a new value type and that is via a struct or an enum. An enumeration actually has an extra class between the value type and the generated enum called System.Enum. We can see the inheritance relationship in the following diagram.

System.ValueType Inheritence

System.ValueType
You might have rarely if ever noticed this class because it is special. You are not allowed to derive from it yourself and so only the compiler can create value types that derive from it directly, which is does for struct definitions. It overrides the implementation of the Equals,  GetHashCode and ToString in order to provide the semantics you would expect for a value type instead of those for a reference type.

System.Enum
The compiler uses this as the base class for all enum definitions. Although it looks as if you can define the base class by specifying something like public enum : short, this is merely syntactic sugar making it easy for you to define how the enumeration values are stored.

Reference Classes
All the blue boxes in the above diagram are reference classes. Yes, it is somewhat ironic that the value type is actually a reference type itself! This means that if you cast a value type instance to System.ValueType then your value will be boxed into a reference. Really it is no different to casting to System.Object. All enum types have the additional ability to be cast to System.Enum and likewise they will be boxed.

Value Types
The red boxes show the two ways of creating new value types.

Built-in Types
Orange boxes show how the well-known built-in types are implemented. They are all struct definitions that also implement various interfaces. You can see this for yourself by using Visual Studio and right-clicking an int keyword and selecting the Go To Definition.

System.Int32

The Nullable generic type is just a structure with a type parameter constraint to ensure it only works with value types.

System.Nullable

There are few uses for System.ValueType but one is using it as a parameter type. This allows the caller to pass any value type such as long, bool, decimal, double, nullable, struct or enum. But it prevents the passing of a reference type. Granted, there are not many times when you need to restrict the passed parameter to the full set of value types but when you need the ability you do have a solution. But do remember that the passed in value will have been boxed!

Additional Resources
MSDN – System.ValueType 

Categories: CLR Tags: ,

WPF: Exception Handling

September 19, 2011 3 comments

I recommend reading the CLR: Exception Handling post before continuing.

A WPF application provides additional events for processing unhandled exceptions in additional to those already offered by the CLR via the AppDomain. To see this we will create a simple application that adds a Button to the main form and throws an exception when it is pressed. Here is the code added to the to the application code-behind file so we can see which events are fired and in what order.

    public partial class App : Application
    {
        public App()
        {
            AppDomain.CurrentDomain.FirstChanceException +=
                new EventHandler(FirstChance);

            AppDomain.CurrentDomain.UnhandledException +=
                new UnhandledExceptionEventHandler(Unhandled);

            this.DispatcherUnhandledException +=
                new DispatcherUnhandledExceptionEventHandler(AppUnhandled);

            this.Dispatcher.UnhandledException +=
                new DispatcherUnhandledExceptionEventHandler(DispUnhandled);

            this.Dispatcher.UnhandledExceptionFilter +=
                new DispatcherUnhandledExceptionFilterEventHandler(DispFilter);
        }

        static void FirstChance(object sender, FirstChanceExceptionEventArgs e)
        {
            Console.WriteLine("AppDomain.FirstChanceException");
        }

        static void Unhandled(object sender, UnhandledExceptionEventArgs e)
        {
            Console.WriteLine("AppDomain.UnhandledException");
        }

        static void AppUnhandled(object sender, DispatcherUnhandledExceptionEventArgs e)
        {
            Console.WriteLine("Application.UnhandledException");
        }

        static void DispUnhandled(object sender, DispatcherUnhandledExceptionEventArgs e)
        {
            Console.WriteLine("Dispatcher.UnhandledException");
        }

        static void DispFilter(object sender, DispatcherUnhandledExceptionFilterEventArgs e)
        {
            Console.WriteLine("Dispatcher.UnhandledExceptionFilter");
        }
    }

The XAML for adding a Button and the Click event handler that throws an exception is too trivial to bother listing here. When our example is run we get the following.

WPF UnhandledException

Pressing the button gives the following message.

WPF FirstChanceException

MSDN documentation indicates that the user should be given a dialog box with exception details followed by the application exiting. I have never seen the supposed dialog box appear but as we can see above it certainly does terminate. This is actually the same end result as occurs when using a bare console application but we do get some additional events. The sequence of events generated is as follows.

WPF Exception Handling

Dispatcher Exception Handling
A dispatcher in WPF is responsible for managing a queue of messages for a thread and dispatching them in priority order. Each WPF thread has an associated dispatcher and has two events relating to exception handling.

The first is UnhandledExceptionFilter which has the sole purpose of allowing you to decide if the exception event of the Dispatcher and Application should fire. It does not however prevent the exception from propagating to the default application domain and terminating the application. If you have some standard logic inside the dispatcher/application instances and for some reason you want to avoid it being called you could handle this event.

When the filter does not prevent it the Dispatcher.UnhandledException event is fired. This allows you to handle the event on a per-thread basis as each thread has its own dispatcher instance. An interesting feature of this event is ability to set the exception as handled and so prevent the application from terminating.

Application Exception Handling
The application instance has the DispatcherUnhandledException event which acts as a central point for any such exception occurring no matter which dispatcher it originated from. So if you have multiple threads and each has its own dispatcher you can choose to hook into the application event and know it will fire no matter which thread the exception originated on. It also has an event argument called Handled that can be used to prevent the exception propagating to the app domain and so exiting the program.

Additional Resources
MSDN – Dispatcher.UnhandledEvent
MSDN – Dispatcher.UnhandledEventFilter
MSDN – Application.DispatcherUnhandledEvent

Categories: WPF Tags: ,

WinForms: Exception Handling

September 18, 2011 2 comments

I recommend reading the CLR: Exception Handling post before continuing.

When building a WinForms application you need to be aware that the default CLR behaviour is modified by WinForms. We can see this most clearly using an example application. Create a new windows forms project and then use the designer to add a Button to the Form1 class. All the project code, excluding the auto-generated code for the Form1 window, is as follows.

    public partial class Form1 : Form
    {
        [STAThread]
        static void Main()
        {
            AppDomain.CurrentDomain.UnhandledException +=
                new UnhandledExceptionEventHandler(Unhandled);

            Application.EnableVisualStyles();
            Application.Run(new Form1());
        }

        static void Unhandled(object sender, UnhandledExceptionEventArgs e)
        {
            Console.WriteLine("UnhandledException Handler");
        }

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            throw new ApplicationException("Button Throw Exception");
        }
    }

When run we get the following window.

WinForms UnhandledException

Pressing the button invokes the button1_click event handler and throws an exception.

WinForms Exception Dialog

Without WinForms we would have expected the CLR to fire the UnhandledException event for the current application domain and then terminate. Instead the user sees the above dialog box. But where did the dialog come from and can we prevent it from appearing?

Message Loop Processing
WinForms is just a wrapper around the Win32 subsystem that uses windows messages for handling eventing in the windowing system. Therefore our application must have a message loop in order to ensure that windows messages are constantly pulled from the message queue and dispatched to the appropriate target window. Without this the user interface would be frozen and unable to respond. This message loop is implemented for us when we call the Application.Run static method.

As application code is always executed from dispatching a windows message it is easy to catch any exception generated by application code. Effectively the dispatch call is contained inside a try/catch which then shows the dialog we have seen above.

Overriding WinForms Dialog
Hook into the Application.ThreadException event in order to implement your own unhandled exception behaviour. Note that the mere act of hooking into this event will prevent WinForms from showing the default dialog. If all you require is to prevent the dialog appearing then simply hook the event with a handler that does nothing.

        [STAThread]
        static void Main()
        {
            Application.ThreadException +=
                new ThreadExceptionEventHandler(ThreadException);
            Application.Run(new Form1());
        }

        static void ThreadException(object sender, ThreadExceptionEventArgs e)
        {
            Console.WriteLine("ThreadException Handler");
        }

Note however that the application will not terminate when the exception is ignored. If you still want the application to terminate you would need to exit the application yourself or you could simply rethrow the exception. The rethrow is outside the WinForms exception handling and so it will obey the usual CLR rules and end up at the application domain UnhandledException handler.

This is the method I would recommend as it means that the same AppDomain.CurrentDomain.UnhandledException handler is fired for non-UI threads as for WinForms threads. Giving complete consistency across your application and a common way of logging problems from all locations. This is the simple code to achieve that.

        [STAThread]
        static void Main()
        {
            AppDomain.CurrentDomain.UnhandledException +=
                new UnhandledExceptionEventHandler(Unhandled);

            Application.ThreadException +=
                new ThreadExceptionEventHandler(ThreadException);

            Application.Run(new Form1());
        }

        static void Unhandled(object sender, UnhandledExceptionEventArgs e)
        {
            Console.WriteLine("UnhandledException Handler");
        }

        static void ThreadException(object sender, ThreadExceptionEventArgs e)
        {
            Console.WriteLine("ThreadException Handler");
            throw e.Exception;
        }

Additional Resources

MSDN – Application.ThreadException
MSDN – Application.SetUnhandledExceptionMode

Categories: WinForms Tags: ,
Follow

Get every new post delivered to your Inbox.