Click here to Skip to main content
15,896,557 members
Articles / Programming Languages / C#

Async Lock In C#

Rate me:
Please Sign up or sign in to vote.
4.27/5 (4 votes)
16 Sep 2019CPOL1 min read 13.8K   6   2
The lock statement was introduced in c# 2.0 to prevent multi threads access to an object at the same time.. In async programming model the goal of the locks is to limit the number of concurrent execution of a block of code to a defined number..

The lock statement was introduced in c# 2.0 to prevent multi threads access to an object at the same time.

Image 1

In async programming model the goal of the locks is to limit the number of concurrent execution of a block of code to a defined number.

While Microsoft introduced a lot of threads synchronization mechanisms , we will only discuss the SemaphoreSlim in this article.

Example

class DataManger
    {
        private DbSet<string> _users;
public DataManger(DbSet<string> users)
        {
            _users = users;
        }
public async Task AddUser(string username)
        {
            await _users.AddAsync(username);
        }
    }

for some reasons we need to limit the number of calls to addUser method to 3 calls at a time.

static SemaphoreSlim _semaphoreSlim = new SemaphoreSlim(3);
        public async Task AddUser(string username)
        {
            await _semaphoreSlim.WaitAsync();
            await _users.AddAsync(username);
           _semaphoreSlim.Release();
        }
static SemaphoreSlim _semaphoreSlim = new SemaphoreSlim(3);

the semaphoreSlim act as lock , we initialize it by setting the maximum number of concurrent request to 3 requests

await _semaphoreSlim.WaitAsync();

if the number of current concurrent requests is less then 3 , it will decrease it by 1, otherwise it will wait until one of the other threads release.

_semaphoreSlim.Release();

simply release the semaphore so any pending requests or upcoming requests can execute.

Using Aspect Oriented programming

while the semaphoreSlim look easy to use , it come with a cost as it introduce more boilerplates to the code (the semaphore declaration , the waitasync statement at the start of the method and the release at the end) and even more complexities imagine exceptions in _users.AddAsync may be a better idea will to use try finally block.

This can have some dramatic consequences on your code complexity as you will have to declare a semaphore per every method you which to limit access to it.

As a solution to make my code cleaner, I prefer using Postsharp aspects

[Serializable]
    public class MethodLockedAttribute : MethodInterceptionAspect
    {
        private int maximum_concurrency_number;
        private static ConcurrentDictionary<int,SemaphoreSlim> SemaphoreSlimRepo=new ConcurrentDictionary<int, SemaphoreSlim>(); 
        public MethodLockedAttribute(int maximumConcurrencyNumber)
        {
            maximum_concurrency_number = maximumConcurrencyNumber;
        }
        
public override async Task OnInvokeAsync(MethodInterceptionArgs args)
        {
            SemaphoreSlim semaphore=new SemaphoreSlim(maximum_concurrency_number);
            SemaphoreSlimRepo.GetOrAdd(args.Method.GetMetadataToken(),  semaphore);
            await semaphore.WaitAsync();
          try
           {
            await args.ProceedAsync();
           }
         
         finally
          {
            semaphore.Release();
          }
        }
}

and decorate the target method to be :

[MethodLocked(3)]
        public async Task AddUser(string username)
        {
           await _users.AddAsync(username);
       }

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Austria Austria
I am a software engineer at PlanRadar currently living in Vienna, Austria. My interests range from technology to web development. I am also interested in programming, xamarin, and mobile development.

Comments and Discussions

 
PraiseThanks for sharing Pin
AnotherKen18-Sep-19 8:30
professionalAnotherKen18-Sep-19 8:30 
I like how you shared this information with short concise code.
BugAt best unclear... Pin
spi18-Sep-19 2:40
professionalspi18-Sep-19 2:40 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.