问题描述
我正在开发一个多线程WindowsPhone8应用程序,该应用程序在异步方法中具有关键部分.
I am working on a multi threaded WindowsPhone8 app that has critical sections within async methods.
在使用嵌套异步调用的情况下,有人知道在C#中正确使用信号量/互斥锁的方法吗?在这种方法中,内部方法可能会获取与调用堆栈中已获取的锁相同的锁?我以为SemaphoreSlim可能是答案,但看起来会导致死锁.
Does anyone know of a way to properly use semaphores / mutexes in C# where you are using nested async calls where the inner method may be acquiring the same lock that it already acquired up the callstack? I thought the SemaphoreSlim might be the answer, but it looks like it causes a deadlock.
public class Foo
{
SemaphoreSlim _lock = new SemaphoreSlim(1);
public async Task Bar()
{
await _lock.WaitAsync();
await BarInternal();
_lock.Release();
}
public async Task BarInternal()
{
await _lock.WaitAsync(); // deadlock
// DO work
_lock.Release();
}
}
推荐答案
递归锁是确实是个好主意(IMO;链接是我自己的博客).对于async
代码,尤其是为true.很难使async
兼容的递归锁起作用.我有一个此处的概念验证,但警告是合理的:我不建议不要在生产环境中使用此代码,该代码不将被卷入AsyncEx,并且未经过全面测试.
Recursive locks are a really bad idea (IMO; link is to my own blog). This is especially true for async
code. It's wicked difficult to get async
-compatible recursive locks working. I have a proof-of-concept here but fair warning: I do not recommend using this code in production, this code will not be rolled into AsyncEx, and it is not thoroughly tested.
您应该做的是按照@svick的说明重组代码.像这样:
What you should do instead is restructure your code as @svick stated. Something like this:
public async Task Bar()
{
await _lock.WaitAsync();
await BarInternal_UnderLock();
_lock.Release();
}
public async Task BarInternal()
{
await _lock.WaitAsync();
await BarInternal_UnderLock();
_lock.Release();
}
private async Task BarInternal_UnderLock()
{
// DO work
}
这篇关于用嵌套的异步调用锁定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!