stevenjin 2024-04-18 23:26 采纳率: 97.6%
浏览 1
已结题

AsyncLock使用失效

在使用这种异步锁时,在执行方法中,打印出了不同的线程id,锁应该没有生效吧?求在有task运行的异步方法中,正确使用锁的方式

using Nito.AsyncEx;
 private readonly AsyncLock asyncLock = new AsyncLock();
 private  async Task DeciperData(byte[] byteParam)
 {
    using (await asyncLock.LockAsync())
    {
              await Task.Run(() => {
                      foreach(var item in data){
                            ........
                             Console.WriteLine(Thread.CurrentThread.ManagedThreadId);//打印出了不同的线程id
                      }
                })
    }
}
  • 写回答

3条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-04-18 23:26
    关注

    引自免费微信小程序:皆我百晓生

    在您的代码示例中,AsyncLock 的确被用于同步进入 DeciperSensor 方法的部分,但是您在锁保护的区域内使用了 Task.Run(),这导致了新的工作线程被创建,因此在 foreach 循环内部打印出的线程 ID 可能会不同。为了避免这种情况,您可以直接在锁保护的范围内执行循环操作,而不是将其放在一个新任务中。

    以下是修改后的代码:

    using Nito.AsyncEx;
    
    private readonly AsyncLock asyncLock = new AsyncLock();
    private async Task DeciperSensor(string clientIP, byte[] byteParam)
    {
        using (await asyncLock.LockAsync())
        {
            foreach (var item in data)
            {
                // ... 操作item
                Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
            }
        }
    }
    

    这样,整个 foreach 循环都在锁的保护之下,确保同一时间只有一个线程可以访问这个敏感区域,不会打印出不同的线程 ID。请注意,这里我们移除了 Task.Run(),因为通常来说,如果没有多线程计算密集型操作,直接在同步上下文中处理数据是更好的选择。如果您确实需要并行化处理 data 中的每个元素,可以考虑使用 Parallel.ForEach(),但这通常不与异步锁一起使用,因为 Parallel.ForEach() 已经实现了并发控制。在这种情况下,可能需要重新评估是否真的需要使用异步锁。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 4月26日
  • 已采纳回答 4月18日
  • 修改了问题 4月18日
  • 创建了问题 4月18日

悬赏问题

  • ¥15 微信会员卡接入微信支付商户号收款
  • ¥15 如何获取烟草零售终端数据
  • ¥15 数学建模招标中位数问题
  • ¥15 phython路径名过长报错 不知道什么问题
  • ¥15 深度学习中模型转换该怎么实现
  • ¥15 HLs设计手写数字识别程序编译通不过
  • ¥15 Stata外部命令安装问题求帮助!
  • ¥15 从键盘随机输入A-H中的一串字符串,用七段数码管方法进行绘制。提交代码及运行截图。
  • ¥15 TYPCE母转母,插入认方向
  • ¥15 如何用python向钉钉机器人发送可以放大的图片?