可以从代码中的多个位置调用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);
}
不允许等待锁定,所以我可以在必要时使用AsyncLock,但尝试保持简单。这段代码是否正确且线程安全?我不确定是否等待Task.WhenAll(taskArray);可以在锁外,我应该使用AsyncLock吗?
答案 0 :(得分:7)
您正在使用的锁几乎没有效果,因为创建任务非常快并且不会与任何内容冲突。在异步设置中实现互斥的方式是使用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
构造来可靠地释放锁。