【问题标题】:Awaiting task array which is executed in lock等待锁定执行的任务数组
【发布时间】:2013-10-28 20:14:44
【问题描述】:

TestAwaitTaskArrayAsync() 可以从代码中的多个位置调用。我需要锁定 taskArray 的执行并异步等待,直到其所有任务完成,然后下一次调用将开始执行 taskArray。代码如下:

private async Task TestAwaitTaskArrayAsync()
        {
            Task[] taskArray;
            lock (_lock_taskArray)
            {
              taskArray = new Task[]
              {
                Task.Run(() =>
                {
                    SomeMethod1();
                }),
                Task.Run(() =>
                {
                    SomeMethod2();
                })
              };
            }
            await Task.WhenAll(taskArray);
        }

Await in lock 是不允许的,所以我可以在必要时使用AsyncLock,但尽量保持简单。此代码是否正确且线程安全?我不确定是否等待 Task.WhenAll(taskArray);可以在锁定之外,我应该使用 AsyncLock 代替吗?

【问题讨论】:

  • 如果你的taskArray 真的是一个局部变量,那么你根本不需要锁定任何东西。
  • @Stephen Cleary,taskArray 是本地的,但是 SomeMethod1() 和 SomeMethod2() 改变了很多变量,所以当 TestAwaitTaskArrayAsync() 被同时调用几次时,结果可能会混合。
  • 在这种情况下,您可能会使用 ConcurrentExclusiveSchedulerPair 和/或 TPL Dataflow 网格找到更好的解决方案。

标签: c# multithreading locking async-await


【解决方案1】:

您使用的锁几乎没有任何效果,因为创建任务非常快并且不会与任何东西冲突。在异步设置中实现互斥的方法是使用 SemaphoreSlim 类。它是一个支持 Task-async 模式的锁。

    SemaphoreSlim sem = new SemaphoreSlim(1);
    private async Task TestAwaitTaskArrayAsync()
    {
        await sem.WaitAsync();
        try {
         Task[] taskArray = new Task[]
           {
             Task.Run(() =>
             {
                 SomeMethod1();
             }),
             Task.Run(() =>
             {
                 SomeMethod2();
             })
           };
         }
         await Task.WhenAll(taskArray);
        }
        finally { sem.Release(); }
    }

以同步方式,这会更容易:

lock (_lock_taskArray)
 Parallel.Invoke(() => SomeMethod1(), () => SomeMethod2());

完成。

如果您愿意,也可以使用AsyncLock。这应该允许您使用using 构造可靠地释放锁。

【讨论】:

  • 这个问题谈到了AsyncLock(虽然没有说是哪一个),这可能也可以。
  • 另外,SemaphoreSlim 没有无参数构造函数。我想你想要new SemaphoreSlim(1)。 (当然,字段不能是var。)
  • @svick 添加了指向 AsyncLock 的链接。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-17
  • 2016-09-19
  • 1970-01-01
  • 2019-09-08
相关资源
最近更新 更多