GUI and worker thread in C#

Download:     Zipped c# application, made in Visual Studio 2005


Accessing GUI control from worker thread was always a problem in Windows OS. This problem did not go away with introduction of C#. Here I offer simple demo of how to manipulate GUI controls from the worker thread. The program demonstrates Central Limit Theorem from statistics



It uses random digit generator to simulate outcome of rolling one die. The distribution is uniform. But when several dice are rolled and outcomes are added the distribution is radically changed and when 3 and more dice involved it start approaching normal distribution. Being more scientific, with small number of dice it is supposed to be Student distribution and turn into normal when number of dice is large enough.
User can select number of dice and size of sequence and start worker thread that performs computations. During computation user can manipulate other controls, terminate thread and application. When thread finished computations the histogram of distribution of sums of selected number of dice values is drawn. The thread should also enable/disable of some buttons allow or disallow user to use certain controls according to a thread state. It also controls the progress bar at the bottom.

The GUI thread is always conflicting with worker thread in Windows applications. And in many applications programmer wants to start worker thread and keep GUI controls responsive to user actions while computation continues. It also would be nice to have this worker thread to report its state by the progress bar or other. There are several ways of achieving this goal. One of them is to pass GUI object and delegate to worker thread and call Invoke method of GUI object inside the worker thread. It may be more clear when looking at several formal operation we need to perform in order to achieve the goal.



In the code above you can see only critical operations required for accessing GUI control from worker thread. They are:
  • Delcaration of delegate class that holds signature of the method DelegateShowHistogram.
  • Delcaration of delegate myDelegateShowHistogram and making delegate instance for reference function ShowHistogram(...) using new operator.
  • Passing this delegate along with GUI object to worker thread myThreadClassObject.Run(...)
  • Calling Invoke method inside worker thread formControl.Invoke(...) and passing this delegate back with parameters.
It is not very hard to remember. The only thing that has to be remembered is that GUI control (formControl) has to be passed to the worker thread and that method formControl.Invoke() should be called inside the thread. Everything else is obvious because Invoke() method takes delegate as parameter that means this delegate has to be created and made available within the thread in one way or another.

There are some other methods of calling GUI from worker thread. I added one alternative method and tested but don't use it in my example. That does not mean that method is not good. This method simplify calls by introduction of static helper class SaveInvokeHelper. The usage is obvious from the code. It may look simpler because when calling SaveInvokeHelper there is no need to create and pass delegates. Unfortunately, SaveInvokeHelper works with Form object only and has to be changed to support also Control object, while the method shown above works in the same way with every particular Control object.

Andrew Polar. Aug. 21, 2009.