C#中的异步锁

本文探讨了在C#中使用SemaphoreSlim进行并发控制的方法,特别是在异步编程中限制对特定方法的并发访问次数。通过具体示例展示了如何利用SemaphoreSlim来避免过多的并发请求,确保系统的稳定性和响应性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C2.0中引入了lock语句,以防止多线程同时访问一个对象。

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

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

class DataManger
    {
        private DbSet<string> _users;
public DataManger(DbSet<string> 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<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();
          }
        }
}

并将目标方法装饰为:

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值