|
||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
IntroductionWe all know about .NET background threads. Background threads are the kind of threads that don't vote for application exit. Consider an application that has a non-background thread and 20 background threads; then, upon exit of the non-background thread, the application exits (all the 20 background threads halt abruptly). But, consider the following cases:
In all the above mentioned cases, the background thread needs to live a little longer than the application exit. The design goal is to have the background thread at least reach a check-point where it can safely shut down after application exit. Another factor to consider while designing the above mentioned background thread is: the application being restarted by the user anytime immediately after the closing. This article is about the worker background thread that wishes to live a little longer than application exit. The aim of this article is to give a brief overview, while the real world solution requires modifications as described in the 'Points of interest' section. BackgroundA real life example: consider I have an attractive download application. When the user chooses to close the application (not tray minimize, but terminate the application), I would like to store my partial downloads. But, being a user-friendly application, I would like to cut-off the User Interface (stop message pump) immediately. At this point, I have a requirement to have the background thread to live a little longer to do the persistence and cleanup work. Also, I risk the application being restarted by the user before the background thread finishes the job. To give one more real life example: consider a medical application that needs to shutdown a connected instrument robot before application exit. The application has a specific UI element (such as a 'Shut Down' button) provided for this functionality. But, say, the user closes the application without shutting down the instrument. Now, such a background thread may be used to have the shutdown sequence executed. This can be done while the UI is removed off the scene immediately. Also one more point worth mentioning here is – Most of the customers hate the application that takes longer time to exit showing dead inactive UI elements for few seconds before exit. Using the codeNow, it is time for the design. The design goal is to have a class that provides the above mentioned functionality. Let's name this class
The error and exception handling are avoided for brevity. using System;
using System.Threading;
/// <summary>
/// Stealthy Background Thread
/// </summary>
public class NonExitBackgroundWorker
{
public delegate void MainMethod();
public delegate void ThreadStart();
private static EventWaitHandle EventToStartApplication;
private static bool m_bCreatedNew;
private static bool m_bWaitForExit;
private static MainMethod MainMethodDelegate;
static NonExitBackgroundWorker()
{
EventToStartApplication = new EventWaitHandle(false, EventResetMode.AutoReset,
"MyEvent43997C2F-33A4-49e1-B5C4-7BC0FE6C6BCF", out m_bCreatedNew);
m_bWaitForExit = false;
if (!m_bCreatedNew)
{
EventToStartApplication.Set();
Environment.Exit(0);
}
}
public static void RegisterMainMethodAndBackgroundThread(MainMethod MainMethodFunc,
ThreadStart ThreadStartFunction)
{
if (!m_bWaitForExit)
{
MainMethodDelegate = new MainMethod(MainMethodFunc);
AsyncCallback theAsyncCallbackToCloseApp =
new AsyncCallback(StopApplicationAndBKThread);
ThreadStartFunction.BeginInvoke(theAsyncCallbackToCloseApp, null);
System.Threading.Thread thApplicationStartListener =
new System.Threading.Thread(ApplicationStartListener);
m_bWaitForExit = true;
thApplicationStartListener.Start();
}
}
private static void ApplicationStartListener()
{
while (m_bWaitForExit)
{
if (EventToStartApplication.WaitOne() && m_bWaitForExit)
{
MainMethodDelegate.BeginInvoke(null, null);
}
}
}
public static void StopApplicationAndBKThread(IAsyncResult AsynchResult)
{
m_bWaitForExit = false;
EventToStartApplication.Set();
}
public static void StartApplication() { }
}
Now, let us walk through the code: The first method is the static constructor The second method, which is also an important function, is The third method is the The fourth method How to use the attached sampleThe attached sample contains a simple C# application, with a UI as shown in the figure above. The background thread will be alive (doing its last minute critical task until you press the 'Shut down App…' button. You can try to close the UI by pressing the 'x' at the top right hand side. Try to restart the application. Now, you will see the same instance starting the UI, while the new instance goes away. This can be verified by looking at the PID in the Task Manager. Points of interestThere are many points necessary to consider while using this class for commercial application development:
|
|||||||||||||||||||||||||||||||||||