用嵌套的异步调用锁定 [英] Locking with nested async calls

查看:94
本文介绍了用嵌套的异步调用锁定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个多线程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
}

这篇关于用嵌套的异步调用锁定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆