Async programming and scalability with C# 5

What is Scalability?

Scalability is the ability of a system to expand to meet your business needs. You scale a system by adding extra hardware or by upgrading the existing hardware without changing much of the application. In the context of a BizTalk Server system, scalability refers to the ability of BizTalk to scale as your throughput needs increase, and if you need to reduce latency times.

From: https://msdn.microsoft.com/en-us/library/aa578023.aspx

Example of non-scalable server:

In ASP.NET each HTTP request is handled by the Thread Pool. The Thread Pool gets the HTTP request, and if there is no available thread in the pool, the Thread Pool will create a new thread in order to process the request.

For example let say that the server is responsible to manage music library, and the client wants to get specific album from the server.
In this case, the client request needs to get the result from other server, aka SQL server data base.

If the server send request to the data base synchronously then the current thread will block until the data will back from the data base.  Blocking threads can hit the scalability of the server.

This scenario cause the server waist most of the time for creating threads, block the threads, and context switching.

g

Improve scalability of the server with asynchronous calls:

Instead of issue the request for the data base synchronously and block the thread until the data comes back from the data base. We can use the async await keywords in order to create asynchronous request against the data base or any other remote server.

The following example demonstrates create asynchronous query against SQL data base using entity framework async API:

public async Task GetAlbunAsync(int id)
{
     using (var context = new RecordsContext())
     {
        return await context.Albums.FirstOrDefaultAsync(album => album.Id == id);
     }
 }

This example creates IO bound request against SQL server asynchronously. That allows this current running thread to go back to the thread pool when waiting to SQL response, instead of blocking the thread. Then the thread pool can use this thread to handle other client requests.

Synchronization:

We all know that Synchronization used to prevent data corruption when two threads access shared data at the same time.  By using the lock statement we ensure that only one thread can update the shared data at a time. This scenario can impact application performance and scalability.
The problem of lock statement:

If we take a look at the Erick Lippert post from 2009: https://blogs.msdn.microsoft.com/ericlippert/2009/03/06/locks-and-exceptions-do-not-mix/

In C# the lock statement is just a syntactic sugar to simplify calls for Monitor.Enter and Monitor.Exit.

When we write the following lock statement:

public void SyncWithLockStatement()
{
   lock (_locker)
   {
	//Do something
   }
}

The compiler translates the statement into:

public void SyncWithLockStatement()
{
   bool sync = false;
   try
   {
      Monitor.Enter(_locker, ref sync);
      //Do Something
   }
   finally {
      if (sync)
      {
           Monitor.Exit(_locker);
      }
   }
 }

At the first glance of this code, its looks very good, the finally statement guaranteed that the Monitor release the lock, and this prevent the application from get into dead lock. But it can corrupt data in the application. For example let’s say that inside the lock statement the code try to execute money transfer transaction between two bank accounts. If exception is thrown right after subtract from first account and before add the amount to second account, the finally will release the lock, the bank accounts will stay with corrupted data, and the application will continue to run.
Therefore we must to catch any exception inside the lock statement in order to avoid corrupt the data.

Asynchronous Lock:

Synchronize shared data by using the lock statement can block the current thread. This can hit the scalability of the server. Therefore in order to increase the scalability of the server we need to avoid blocking threads. But we still have to synchronize our shared data.
In .NET 4.5 we can use the SemaphoreSlim.WaitAsync method in order to synchronize our data without blocking threads.

For Example:

private static SemaphoreSlim sync = new SemaphoreSlim(1);
public async Task AddAlbumAsync(Album album)
{
    using (var context = new RecordsContext())
    {
           await sync.WaitAsync();
           context.Albums.Add(album);
           await context.SaveChangesAsync();
           sync.Release();
     }
 }

Stephen Toub blog: https://blogs.msdn.microsoft.com/pfxteam/2012/02/12/building-async-coordination-primitives-part-6-asynclock/
Demonstrate how to create AsyncLock type that supports interaction with the ‘using’ keyword.
Conclusion:
Asynchronous programming can be very useful when we have to create IO bound requests against remote server.

Advertisements

About Idan Reuven

Idan is Microsoft Certified Proffesional Developer (MCPD) Idan Working As Senior Software developer. and specialize in professional application development with WPF, WCF, Entity Framework, XAML, HTML 5, Java Script , jQuery, MVC, MVVM, C#, C++, SQL Server Technologies.
This entry was posted in .NET, .NET 4.5, C# 5. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s