Correct organization of event processing in a separate thread
Multithreaded application became something common. The main reason for that is execution of resource-intensive tasks in parallel to GUI without stopping it for long operations. As it is well known, the easiest way for asynchronous data processing used by ThreadPool. This method is not only the easiest, but also very efficient. Notwithstanding its merits, it has one large backdraw – an application cannot manage ThreadPool lifetime and cannot be confident that during termination ThreadPool doesn’t process previously assigned tasks that may cause application crash.
Let’s review a specific case of threadpool implementation consisting of a single thread. The requirements to this implementation are:
Delay between adding task to threadPool and initiation of its execution should be minimal
If there are no tasks, threadpool should not consume resources. Specifically, context switches should not be allocated to thread that doesn’t process tasks
Threadpool should provide an interface (IDisposable is the best for it) for correct work termination and guarantee that upon Dispose() call, all tasks including tasks in execution shall be completely terminated.
Tasks should be executed in sequence without acquiring synchronizing objects.
Enable recursive task execution
Providing interface for exception handling.
So, there are many requirements and all of those are sufficient. Monitor class is most convenient to implement thread synchronizations. It allows to protect task queue and to move thread to sleep state where it doesn’t consume resources and take it out of this state upon receiving a signal. On adding a new task to the queue and on thread termination request a signal should be sent to this thread. Another useful property of the Monitor is recursive and safe acquiring of the same synchronizing object enabling recursive task addition.
Now let’s review the process of thread pool termination. When a new thread is launched, it is transmitted a method called by the newly created thread. This method usually contains a task processing loop. During execution this cycle constantly checks value of a flag that specifies whether it is necessary to stop task processing. This flag is initially set to false, but Dispose function is set to true. When the calling thread sets this flag to true and notifies the threadpool about it, this thread should wait until threadPool execution ends using Join() method. If threadpool execution doesn’t end in allocated time, the calling thread may be forcibly terminated using Abort().
Exception handling. All task exceptions occur in threadPool thread. Therefore, if it they are not processed, the thread stops. To prevent it, the thread should catch all exceptions occurring during task execution. In a well designed system threadpool should provide interface for notification of extraordinary situation. UnhandledException event is most suitable for this purpose.
As new thread is not launched instantly, to prevent sending tasks to uninitialized thread, it is reasonable to add Monitor to thread start at threadPool.
About the Author
Dapfor .net grid has been created by professional developers with extensive experience in banking and telecommunication fields. .Net Grid is the best performing grid on the market adapted for real-time applications (trading software, real time trading, real time blotter) and displaying huge data volumes. Thread protection makes it safe to use with MVVM model.