この種のコンテキストで使用される、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;
}
Asyncメソッドがある場合は、可能であれば呼び出しのブロックを回避する必要があります。 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
はブロックしないことです。