异步方法中的信号量等待与 WaitAsync
Semaphore Wait vs WaitAsync in an async method
我试图找出在这种上下文中使用的 Wait 和 WaitAsync 的 SemaphoreSlim 之间的区别:
private SemaphoreSlim semaphore = new SemaphoreSlim(1);
public async Task<string> Get()
{
// What's the difference between using Wait and WaitAsync here?
this.semaphore.Wait(); // await this.semaphore.WaitAsync()
string result;
try {
result = this.GetStringAsync();
}
finally {
this.semaphore.Release();
}
return result;
}
区别在于Wait
会阻塞当前线程直到信号量被释放,而WaitAsync
不会。
如果您有异步方法 - 您希望尽可能避免任何阻塞调用。 SemaphoreSlim.Wait()
是阻塞调用。那么如果你使用 Wait()
并且此时信号量不可用会发生什么?它会阻塞调用者,这对于异步方法来说是非常意想不到的事情:
// this will _block_ despite calling async method and using await
// until semaphore is available
var myTask = Get();
var myString = await Get(); // will block also
如果您使用 WaitAsync
- 如果此时信号量不可用,它不会阻止调用者。
var myTask = Get();
// can continue with other things, even if semaphore is not available
此外,您还应注意将常规锁定机制与 async\await 一起使用。这样做之后:
result = await this.GetStringAsync();
您可能在 await
之后在另一个线程上,这意味着当您尝试释放您获得的锁时 - 它可能会失败,因为您试图从您获得它的同一个线程中释放它。请注意,这是 NOT 信号量的情况,因为它没有线程亲和性(不同于其他此类构造,如 Monitor.Enter
、ReaderWriterLock
等)。
我试图找出在这种上下文中使用的 Wait 和 WaitAsync 的 SemaphoreSlim 之间的区别:
private SemaphoreSlim semaphore = new SemaphoreSlim(1);
public async Task<string> Get()
{
// What's the difference between using Wait and WaitAsync here?
this.semaphore.Wait(); // await this.semaphore.WaitAsync()
string result;
try {
result = this.GetStringAsync();
}
finally {
this.semaphore.Release();
}
return result;
}
区别在于Wait
会阻塞当前线程直到信号量被释放,而WaitAsync
不会。
如果您有异步方法 - 您希望尽可能避免任何阻塞调用。 SemaphoreSlim.Wait()
是阻塞调用。那么如果你使用 Wait()
并且此时信号量不可用会发生什么?它会阻塞调用者,这对于异步方法来说是非常意想不到的事情:
// this will _block_ despite calling async method and using await
// until semaphore is available
var myTask = Get();
var myString = await Get(); // will block also
如果您使用 WaitAsync
- 如果此时信号量不可用,它不会阻止调用者。
var myTask = Get();
// can continue with other things, even if semaphore is not available
此外,您还应注意将常规锁定机制与 async\await 一起使用。这样做之后:
result = await this.GetStringAsync();
您可能在 await
之后在另一个线程上,这意味着当您尝试释放您获得的锁时 - 它可能会失败,因为您试图从您获得它的同一个线程中释放它。请注意,这是 NOT 信号量的情况,因为它没有线程亲和性(不同于其他此类构造,如 Monitor.Enter
、ReaderWriterLock
等)。