C#锁定和异步方法

时间:2013-11-19 23:51:19

标签: c# multithreading

我不清楚(并且找不到足够清晰的文档):在异步方法中使用lock关键字时:如果对象已被阻止,线程是否会被阻塞,或者它是否会以挂起状态返回任务(不是阻塞线程,并在释放锁时返回?)

在下面的代码中,该行会阻塞线程吗?如果它阻塞线程(这是我的想法),是否有标准的阻塞解决方案?我正在考虑使用AsyncLock,但首先我想尝试标准的东西。

感谢。

private object myLock = new object(); 

private async Task MyMethod1(){
  lock (myLock ) {// <---- will this line cause a return of the current method as an Await method call would do if myLock was already locked. 

    .... 
  }
}

// other methods that lock on myLock

4 个答案:

答案 0 :(得分:35)

  

在下面的代码中,该行会阻塞线程吗?

从技术上讲,是的,但它不会像你期望的那样工作。

有两个原因可以解释为什么线程仿射锁与async不能很好地配合。一个是(在一般情况下),async方法可能无法在同一个线程上恢复,因此它将尝试释放它不拥有的锁,而另一个线程永远持有锁。另一个原因是在持有锁的await期间,在锁定时可以执行任意代码。

出于这个原因,编译器不再允许在await块内禁止lock表达式。不过,你仍然可以直接使用Monitor或其他原语拍摄自己。

  

如果它阻塞了线程(这是我的想法),是否有标准的非阻塞解决方案?

是; SemaphoreSlim类型支持WaitAsync

答案 1 :(得分:6)

这是不允许停止僵局(即开发人员伤害自己)。我发现的最佳解决方案是使用信号量 - See this post for details

相关代码摘录:

    running build_ext
    building 'pycocotools._mask' extension
    C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\amd64\cl.exe /c /nologo /Ox /MD /W3 /GS- /DNDEBUG -IE:\Anaconda2\Lib\site-packages\numpy\core\include -I../common -IE:\Anaconda2\include -IE:\Anaconda2\PC /Tcpycocotools/_mask.c /Fobuild\temp.win-amd64-2.7\Release\pycocotools/_mask.obj -Wno-cpp -Wno-unused-function -std=c99
    cl : Command line error D8021 : invalid numeric argument '/Wno-cpp'
    error: command 'C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\BIN\\amd64\\cl.exe' failed with exit status 2

答案 2 :(得分:4)

不,不会。

lockMonitor.EnterMonitor.Exit的语法糖。 lock将继续执行该方法,直到锁定被释放。它在任何方式,形状或形式上都不像await那样。

答案 3 :(得分:2)

您的任务不会以暂停状态返回。它会等到myLock解锁后才能在lock语句中运行代码。无论您使用什么C#异步模型,都会发生这种情况。

换句话说,没有两个线程能够在锁内运行语句。除非,myLock对象有许多不同的实例。