use*_*861 3 .net multithreading asynchronous semaphore locking
如今,在异步代码中,SemaphoreSlim 似乎是lock(obj) {}
. 我找到了有关如何使用它的建议:
https ://blog.cdemi.io/async-waiting-inside-c-sharp-locks/
特别是,此人建议使用以下代码:
//Instantiate a Singleton of the Semaphore with a value of 1. This means that only 1 thread can be granted access at a time.
static SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1,1);
Run Code Online (Sandbox Code Playgroud)
//Asynchronously wait to enter the Semaphore. If no-one has been granted access to the Semaphore, code execution will proceed, otherwise this thread waits here until the semaphore is released
await semaphoreSlim.WaitAsync();
try
{
await Task.Delay(1000);
}
finally
{
//When the task is ready, release the semaphore. It is vital to ALWAYS release the semaphore when we are ready, or else we will end up with a Semaphore that is forever locked.
//This is why it is important to do the Release within a try...finally clause; program execution may crash or take a different path, this way you are guaranteed execution
semaphoreSlim.Release();
}
Run Code Online (Sandbox Code Playgroud)
对我来说,这段代码似乎违反了我以前看到的有关如何锁定的建议,即要记住您的代码可能随时被中断并为此编写代码。await sempahoreSlim.WaitAsync()
如果在进入 try 语句之前和之后抛出任何异常,则信号量将永远不会被释放。这种问题正是我认为引入 lock 语句和 using 语句会取得如此好的效果的原因。
是否有参考文献可以明确解释该代码是有效的?也许 try/finally 语句实际上是在代码被中断之前输入的,这是我以前从未了解过的?或者,是否有一种不同的模式实际上可以正确使用信号量作为锁,或者异步 .NET 代码的其他一些锁定机制?
是的,理论上,在await semaphoreSlim.WaitAsync();
和 之间确实可能会发生一些事情try
,但实际上:在这种情况下,您的应用程序已经是烤面包了,因为它正处于调用堆栈内爆的过程中。实际上,虽然这是一个理论上的问题,但无论如何您都无能为力,并且您的过程将像它本身那样令人厌恶地被不优雅地放下。
所以我的建议是:不要太担心:)
(实际上,更大的风险是线程池的死亡螺旋,通常是由线程池线程上的异步同步引起的,这意味着即使您从语义上获取了信号量,也没有池线程可以提供给你实际做这件事,让你可以重新发布它)