ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

解决 lock 无法跨 await 问题

解决 lock 无法跨 await 问题 你定义的这行代码非常标准是解决lock无法跨await问题的正确做法。privatereadonlySystem.Threading.SemaphoreSlimdataBandLocknewSystem.Threading.SemaphoreSlim(1,1);这里的(1, 1)含义是第一个1初始可用许可数为 1同一时刻只允许一个线程进入。第二个1最大许可数为 1防止释放时超额增加许可。这等价于一个异步版本的lock。✅ 正确使用方式使用WaitAsync()替代lock的进入用Release()替代lock的退出并且必须放在try/finally中确保异常时也能释放awaitdataBandLock.WaitAsync();try{// 这里可以安全地 await锁会被正确保持stringstrresultawaitAPIHelper.HttpPostRestRequestAwait(ApiUrls.findInventoryQuestionList,strjson);// 处理结果...}finally{dataBandLock.Release();}⚠️ 常见坑点必须用try/finally如果WaitAsync()之后的代码抛异常而没有Release()信号量将永远保持为 0后续所有请求都会被永久阻塞。这是最常见的致命错误。不要忘记Release()的次数要匹配SemaphoreSlim(1, 1)每次WaitAsync成功占用一个许可就必须对应一次Release()。多释放会抛SemaphoreFullException。考虑加超时可选但推荐如果担心死锁或长时间等待可以传入超时if(!awaitdataBandLock.WaitAsync(TimeSpan.FromSeconds(10))){// 超时处理比如记录日志、返回错误return;}try{...}finally{dataBandLock.Release();}不要锁整个耗时操作如果没必要如果await的 HTTP 请求并不需要串行执行仅“更新共享数据”这一步需要保护那么应该缩小锁定范围stringstrresultawaitAPIHelper.HttpPostRestRequestAwait(...);// 并发执行awaitdataBandLock.WaitAsync();try{// 只保护共享状态更新listReviewNewEntity...;}finally{dataBandLock.Release();}这样能显著提升吞吐量。IDisposable释放可选SemaphoreSlim实现了IDisposable。如果这个类本身实现了IDisposable建议在Dispose中调用dataBandLock.Dispose()。不过对于生命周期与类一致的长驻字段不释放通常问题不大。
返回列表