将 ManualResetEvent 与异步代码一起使用是否错误?

Cem*_*m.S 2 c# multithreading asynchronous

我正在寻找同步任务的最佳实践(甚至不确定这在语义上是否正确,我可能应该说用异步代码同步线程)。

采取以下代码:

Task.Run(async () => await lib.WaitAsync());
Task.Run(async () => await lib.WaitAsync());
Task.Run(async () => await lib.WaitAsync());

// Synchronize all waiters
lib.Release();

// All Tasks shall be completed
Run Code Online (Sandbox Code Playgroud)

在使用线程时,我曾经使用ManualResetEvent. 所以我的第一个(简化的)方法是:

Task WaitAsync()
{
   await Task.Run(() => manualResetEvent.WaitOne());
} 

void Release()
{
   manualResetEvent.Set();
} 
Run Code Online (Sandbox Code Playgroud)

现在我看到人们已经实现了自己的 async ManualResetEvent

原始方法有什么问题以及为什么有人更喜欢异步实现?是因为取消了吗?异常展开/处理?

更一般地说,在异步代码中使用常规线程同步对象(互斥量、信号量等)是否有任何缺点?

谢谢

The*_*ias 6

Task当从一个内部异步操作进行到下一个内部异步操作时,异步可以使用多个线程,并且在其生命周期的大部分时间里可能根本不使用任何线程。这是所期望的,因为它促进了可扩展性。阻塞线程是一种资源浪费。以及所有线程同步原语 ( Mutex, Semaphore,WaitHandle)都在这样做,它们会阻塞线程。

相反,当使用 限制异步操作​​时,不会阻塞任何线程SemaphoreSlim.WaitAsync,据我所知,这是用于异步阻塞任务的唯一可用的内置机制。