Asynchronous Programming in C# and ASP.NET Framework

Asynchronous programming allows you to execute code in threads. Many classes in .NET allow Asynchronous programming methods with the methods that prefixed withBeginXXX andEndXXX. For instance,FileStream class has aside from Read method, two additional methods such asBeginRead andEndRead.

We can do asynchronous programming in three different ways: Wait-Unitl-Done which allows you start asynchronous call and do other work, Polling which polls IAsyncResult and see if it is finished by calling on IsCompleted method of IAsyncResult, Call Back where we specify any method we need to call back on and we need to include a state of this call back.

Asynchronous programming has following intricacy of exception handling. It does not happen during the asynchronous process but rather during EndXXX call and we need to keep this in mind when trying to handle exceptions within our code.

Now we know quite a bit about Asynchronous programming principles and we can even implement one ourselves but this is not really needed with .NET Framework and C#. The main reason is that .NET Framework already has built in thread pool.
WaitCallback workItem = new WaitCallback(WorkWithParameter));
if (!ThreadPool.QueueUserWorkItem(workItem, "ThreadPooled"))
{
    Console.WriteLine("Could not queue item");
}

Thread pooling is very useful in many ways but first and foremost it helps to reduce processing power of the system by reusing threads instead of creating new once when we need one.

We use WaitCallback when adding to a thread pool and we use AsyncCallback when creating threads manually via BeginInvoke, EndEnvoke

Method of ThreadPool

 

NameDescription
GetAvailableThreads Gets available threads
GetMaxThreads Gets the maximum number of threads
GetMinThreads Gets the minimum number of threads
QueueUserWorkItem Adds a piece of work to the thread pool
RegisterWaitForSingleObject Makes a callback to be issued
SetMaxThreads Sets the max. number of threads
SetMinThreads Sets the min. number of threads
UnsafeQueueNativeOverlapped Used to queue asynchronous File I/O
UnsafeQueueUserWorkItem Queues a work item for a thread for high-performance
UnsafeRegisterWaitForSingleObject Makes a callback for a specific WaitHandle

We may want increase or decrease number of threads available. The two main reasons are: thread starvation and start-up cost. If we need to increase threads because we have too many processes we need to call on ThreadPool.SetMaxThreads or ThreadPool.SetMinThreads if we need to reduce amount of threads.
int threads;
int myCompletionPorts;
ThreadPool.GetMaxThreads(out threads, out myCompletionPorts); // Get
ThreadPool.SetMaxThreads(threads + 10, myCompletionPorts + 100); // Set
ThreadPool.GetMinThreads(out threads, out myCompletionPorts); // Get
ThreadPool.SetMinThreads(threads + 10, myCompletionPorts + 100); // Set

ThreadPool can also work with kernel-level synchronization objects such as Mutex, Semaphore and Event by calling on ThreadPool.RegisterWaitHandle.

In addition, Asynchronous coding varies between Windows Forms and ASP.NET in a way we do implementation. In order to abstract our development from these two forms we employ SynchronizationContext Class. It is also worthwhile to mention Timer object that will trigger asynchronous call to a method based on time we need to execute such a method. We employ delegate to call on the method we need to execute. This is used basically when we need to make reoccurring calls over time.
Timer mytm = new Timer(new TimerCallback(TimerTick), null, 0, 1000);
// Using Infinite
mytm.Change(Timeout.Infinite, 1000); //update timer.
static void MyTimerTick(object state)
{
    Console.WriteLine("Tick");
}