Lock for Async Methods

Despite the intended nature, we seldom might come across situation where we would want to place a lock around an async statement and make it behave differently, especially when accessed from different threads. Let’s try to mock the scenario first to demonstrate the issue.

The lock-async Problem

Consider the following code snippet.

void Main()
{
     Parallel.For(0,5,async (x,y)=>{await TestMethod();});
}

async Task<bool> TestMethod()
{
Console.WriteLine("In");
// Do some tasks here. For demonstration purpose we will use Task.Delay to mock a long running task.
await Task.Delay(2000);
Console.WriteLine("Out");
return await Task.FromResult(true);
}

The output of the above code would be as following, understandably allowing multiple threads to access the ‘intended long running process code‘.

In
In
In
In
In
Out
Out
Out
Out
Out

The most common workaround is placing a lock statement around the code. Try placing a lock around the await statement and you would surprised to know you are not allowed to do so.

“Cannot await in the body of a lock statement”

This is where the trouble starts.

The Solution

The workaround for the issue with Semaphore. Instead of lock, you could use a semaphore to ensure only one/limited threads access the async method at a time.

Let us rewrite the code with semaphore now.

void Main()
{
       Parallel.For(0,5,async (x,y)=>{await TestMethod();});
}
static SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1,1);
async Task<bool> TestMethod()
{
await semaphoreSlim.WaitAsync();
try
{
Console.WriteLine("In");
await Task.Delay(2000);
Console.WriteLine("Out");
}
finally
{
semaphoreSlim.Release();
}
return await Task.FromResult(true);
}

As you can observe, the compile would accept this solution as desired. The output of following can seen below.

In
Out
In
Out
In
Out
In
Out
In
Out

Enjoy coding

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 )

Google+ photo

You are commenting using your Google+ 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 )

Connecting to %s