简体   繁体   English

C# 锁和异步方法

[英]C# Lock and Async Method

I am not clear (and can't find documentation clear enough): when using the lock keyword in an async method: will the thread be blocked if the object is already blocked or will it return a task in suspended state (not blocking the thread, and returning when the lock is released)?我不清楚(并且找不到足够清晰的文档):在异步方法中使用 lock 关键字时:如果对象已经被阻塞,线程是否会被阻塞,或者它是否会返回处于挂起状态的任务(不阻塞线程) ,并在释放锁时返回)?

In the code below, will the line block the thread?在下面的代码中,该行会阻塞线程吗? If it blocks the thread (which is what I think), is there an standard not blocking solution?如果它阻塞线程(这是我的想法),是否有标准的不阻塞解决方案? I am considering using AsyncLock , but first I wanted to try for something standard.我正在考虑使用AsyncLock ,但首先我想尝试一些标准的东西。

thanks.谢谢。

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

In the code below, will the line block the thread?在下面的代码中,该行会阻塞线程吗?

Technically, yes, but it won't work as you expect.从技术上讲,是的,但它不会像您期望的那样工作。

There are two reasons why thread-affine locks don't play well with async .线程仿射锁不能很好地与async配合的原因有两个。 One is that (in the general case), an async method may not resume on the same thread, so it would try to release a lock it doesn't own while the other thread holds the lock forever.一个是(在一般情况下), async方法可能不会在同一线程上恢复,因此它会尝试释放它不拥有的锁,而另一个线程永远持有该锁。 The other reason is that during an await while holding a lock, arbitrary code may execute while the lock is held.另一个原因是在持有锁的await期间,可以在持有锁的同时执行任意代码。

For this reason, the compiler goes out of its way to disallow await expressions within lock blocks.出于这个原因,编译器不遗余力地禁止在lock块中使用await表达式。 You can still shoot yourself in the foot by using Monitor or other primitives directly, though.不过,您仍然可以通过直接使用Monitor或其他基元来用脚射击自己。

If it blocks the thread (which is what I think), is there an standard not blocking solution?如果它阻塞线程(这是我的想法),是否有标准的不阻塞解决方案?

Yes;是的; the SemaphoreSlim type supports WaitAsync . SemaphoreSlim类型支持WaitAsync

This has been disallowed to stop deadlocks (ie developers hurting themselves).这已被禁止以阻止死锁(即开发人员伤害自己)。 The best solution I've found is to use semaphores - See this post for details .我发现的最佳解决方案是使用信号量 -有关详细信息,请参阅此帖子

Relevant code extract:相关代码摘录:

static SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1, 1);

...

await semaphoreSlim.WaitAsync();
try
{
    await Task.Delay(1000);
}
finally
{
    semaphoreSlim.Release();
}

No it won't.不,不会。

lock is syntactic sugar for Monitor.Enter and Monitor.Exit . lockMonitor.EnterMonitor.Exit语法糖。 lock will keep execution in the method until the lock is released. lock会一直在方法中执行,直到锁被释放。 It does not function like await in any way, shape or form.它在任何方面、形状或形式上都不像await那样起作用。

You task will not return in suspended state.您的任务不会以挂起状态返回。 It will wait until myLock is unlocked to run the code within lock statement.它将等到 myLock 被解锁以运行 lock 语句中的代码。 It will happen no matter what C# asynchronous model you use.无论您使用什么 C# 异步模型,它都会发生。

In other words, no two threads will be able to run statements inside the lock.换句话说,没有两个线程能够在锁内运行语句。 Unless, there are many different instances of myLock object.除非,有许多不同的 myLock 对象实例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM