Sunday, March 21, 2010

The asynchronous programming model

The .Net Framework allows you to perform multiple operations at same time, as the processor capability of the machine allows.
For acomplish this, numerous classes have methods with the BeginX and EndX signatures.  This type of methods allows to indicate the begin and the end, respectively, of an asynchronous call. There are three techniques:
  1. Wait until done:  You perform some work between the BeginX and EndX methods, but if the asynchronous call don't has finished his work yet, then the thread will block the application to acomplish this.
  2. Polling:  You poll the IAsyncResult object (returned by the BeginX method) to verify when his property IsCompleted is true, perhaps by a While structure.
  3. Callback:  There is a method that is called when the asynchronous operation it's done.  This method is executed in a different thread.  You need to pass an AsynCallback delegate to the BeginX method.  This delegate will aim to the handler method.  Also, you can pass an Object as the state of the asynchronous operation, like a parameter.
The exceptions occured during the asynchronous call are raised in the EndX  method.  A special case may be considered with Windows Forms applications.  This applications will raise the exceptions 
immediately, showing a dialog to the user an killing the thread.  For manage this, thou need register a handler for the application's ThreadException event.
Normally isn't necessary or even sugested to create manually an Thread object from scratch, as we see in a previous post.  Instead, in the vast majority of cases is most apropiate to use the ThreadPool class, wich allows you to create a pool of threads that the framework controls in an automatic manner.  The most important methods of the ThreadPool class are the following:
  • QueueUserWorkItem:  Allows you to queue a task for execution in the next available thread.
  • GetAvailableThreads:  Returns the number of current available threads in the pool.
  • GetMaxThreads:  Returns the maximum number of threads that the pool can reach, and the maximum number of completion ports (a Kernel related object).
  • GetMinThreads.
  • RegisterWaitForSingleObject: Allows wait in asynchronously manner the termination of a task by an WaitHandle object, wich is a delegate that aims to a method that handles the event of the task conclusion.
  • SetMaxThreads:  This method allows you to increase the maximum threads that the pool can reach.  This helps in cases of thread starvation (your application need wait to much to set work in a new thread).
  • SetMinThreads:  If the setup cost of the threads is expensive, increasing the numer of minimum threads in  the pool can help to improve performance.
  • UnsafeQueueWorkItem:  Works similary to the QueueUserWorkItem method but is for use in high performance scenarios.  The execution context isn't propagated to the new thread.
  • UnsafeRegisterWaitForSingleObject.
The SynchronizarionContext class allows you to stop worriyng about the diferences of the diferent ways in wich the aplication's context handles the asynchronous calls.  Its Send method serves to execute code in a synchronous way, while the Post method tries to execute the code in an asynchronous manner, if the enviroment allows that.  If not, the code is executed synchronously.  This class is very useful if you need to execute an arbitrary code without the need of track the result.
Another useful class is the Timer.  This allows us to perform actions at intervals.  The constructor supports specification of the time to start, the interval, and the method to invoke.

No comments:

Post a Comment

Bookmark and Share