您当前的位置: 首页 > 

寒冰屋

暂无认证

  • 1浏览

    0关注

    2286博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

C#中的异步锁

寒冰屋 发布时间:2019-10-16 21:53:51 ,浏览量:1

在C#2.0中引入了lock语句,以防止多线程同时访问一个对象。

在异步编程模型中,锁的目的是将代码块的并发执行次数限制为定义的次数。

尽管Microsoft引入了许多线程同步机制,但我们仅在本文中讨论SemaphoreSlim。

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

由于某些原因,我们需要将对addUser方法的调用次数限制为一次3次。

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);

semaphoreSlim充当锁,我们通过并发请求的最大数目设置为3个请求初始化它

await _semaphoreSlim.WaitAsync();

如果当前并发请求的数量小于3,则它将减少为1,否则将等待直到其他线程之一释放。

_semaphoreSlim.Release();

只需释放信号量,即可执行任何待处理的请求或即将到来的请求。

使用面向切面的编程

虽然semaphoreSlim看起来易于使用,但要它带来了成本,因为它将更多的样板引入代码中(信号量声明、方法开始处的waitasync语句和结束处的释放),并且更加复杂的是,可以想象_users.AddAsync中的异常,可能一个更好的主意是使用try finally块。

这将对您的代码复杂性产生重大影响,因为您必须为每种方法声明一个信号量以限制对其的访问。

为了使代码更简洁,我更喜欢使用Postsharp切面

[Serializable]
    public class MethodLockedAttribute : MethodInterceptionAspect
    {
        private int maximum_concurrency_number;
        private static ConcurrentDictionary SemaphoreSlimRepo=new ConcurrentDictionary(); 
        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();
          }
        }
}

并将目标方法装饰为:

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

 

关注
打赏
1665926880
查看更多评论
立即登录/注册

微信扫码登录

0.1474s