信号量等待与异步方法中的WaitAsync相同

mo5*_*470 7 c# concurrency semaphore synchronizationcontext

我试图找出在这种情况下使用的SemaphoreSlim使用Wait和WaitAsync之间的区别:

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;
}
Run Code Online (Sandbox Code Playgroud)

Evk*_*Evk 13

如果您有异步方法 - 如果可能,您希望避免任何阻塞调用.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
Run Code Online (Sandbox Code Playgroud)

如果您使用WaitAsync- 如果此时信号量不可用,它将不会阻止调用者.

var myTask = Get();
// can continue with other things, even if semaphore is not available
Run Code Online (Sandbox Code Playgroud)

此外,您应该注意与async\await一起使用常规锁定机制.这样做之后:

result = await this.GetStringAsync();
Run Code Online (Sandbox Code Playgroud)

您可能在另一个线程之后await,这意味着当您尝试释放您获得的锁时 - 它可能会失败,因为您试图不是从您获得它的同一个线程中释放它.请注意,这不是信号量的情况,因为它没有线程关联(与其他类似的结构不同Monitor.Enter,ReaderWriterLock等等).

  • 信号量不是线程仿射的,因此可以从任何线程获取/释放它们.但是,其他锁定机制是线程仿射的. (4认同)

the*_*ric 8

不同的是,Wait在信号量被释放之前阻塞当前线程,而WaitAsync不会。