这些调用是阻塞的还是异步的?

问题描述 投票:0回答:2

这两个片段中

methodX()
的执行是否不同?

SemaphoreSlim _locker
.Wait()
WaitAsync()
是具有同步和异步版本的同一方法的示例:

答:

SemaphoreSlim _locker = new SemaphoreSlim(1);
async Task methodX()
{
   _locker.Wait();
   // .. rest of the code
}

乙:

SemaphoreSlim _locker = new SemaphoreSlim(1);
async Task methodX()
{
   await _locker.WaitAsync();
   // .. rest of the code
}
c# asynchronous async-await
2个回答
14
投票

有趣的问题是如果我们不能立即获取锁会发生什么?

在第一个代码示例中,当前线程将阻塞,并在获取锁时解除阻塞以继续,无需线程转换即可继续。

使用第二个代码示例,

await
将检测不完整状态,并使用状态机附加操作完成时发生的延续,然后展开自身。假设 unroll 到达了驱动线程的任何地方(通常是线程池),那么该线程就可以被重用来执行其他 CPU 工作。在未来的某个时刻,将触发延续并重新激活工作,很可能在不同的线程上(同步上下文可能意味着使用相同的线程,特别是在 WinForms 这样的 UI 环境中)。

这个延续机制有一些(小的)开销——没有什么是免费的,但这意味着你不应该耗尽线程;因此,

await
对于防止高并发服务器上的所有线程处于空闲状态、等待 IO、锁获取等事情非常有用,这样仍然可以完成一些有用的工作。


4
投票

从逻辑上讲,两者都会做同样的事情。仅查看该进程,两者都会在等待指令上阻塞其执行。 不同之处在于,异步版本将允许其他进程在您等待时使用您的计算资源,而同步版本将仅使用您的计算资源来等待。

在大多数情况下,最好尽可能使用异步版本。

© www.soinside.com 2019 - 2024. All rights reserved.