在这段代码中:
public async Task v_task()
{
await Task.Run(() => Console.WriteLine("Hello!"));
}
public async void v1()
{
await v_task();
// some other actions...
}
public void ButtonClick()
{
v1();
Console.WriteLine("Hi!");
}
如果调用 ButtonClick,上述哪些方法实际上是在 async/await 生成的底层线程池中并行执行的?
我的意思是,对于使用 async/await 的竞争条件,我应该担心什么?所有异步方法都必须在同一个调用者的线程中执行吗?我应该在可能的共享状态上使用互斥量吗?如果是,我如何检测共享状态对象是什么?
最佳答案
Which methods above are actually executed in parallel in the async/await generated lower thread pool if ButtonClick is called?
只有 Task.Run
中的 Console.WriteLine
。
I mean, what should be my concerns about race conditions working with async/await?
我建议您先阅读我的 async
intro ,它解释了 await
的实际工作原理。
总而言之,async
方法通常以串行异步 方式编写。以这段代码为例:
CodeBeforeAwait();
await SomeOtherMethodAsync();
CodeAfterAwait();
您总是可以说 CodeBeforeAwait
将首先执行完成,然后调用 SomeOtherMethodAsync
。然后我们的方法将(异步地)等待 SomeOtherMethodAsync
完成,只有在那之后才会调用 CodeAfterAwait
。
所以它是串行异步的。它以串行方式执行,就像您期望的那样,但在该流程中也有一个异步点(await
)。
现在,您不能说 CodeBeforeAwait
和 CodeAfterAwait
将在同一个线程中执行,至少在没有更多上下文的情况下是这样。 await
默认会在当前的 SynchronizationContext
中恢复(如果没有 SyncCtx,则在当前的 TaskScheduler
中恢复)。因此,如果上面的示例方法是在 UI 线程中执行的,那么您就会知道 CodeBeforeAwait
和 CodeAfterAwait
都将在 UI 线程中执行。但是,如果它是在没有上下文的情况下执行的(即从后台线程或控制台主线程执行),则 CodeAfterAwait
可能会在不同的线程上运行。
请注意,即使方法的某些部分在不同的线程上运行,运行时也会在继续该方法之前负责设置任何障碍,因此无需围绕变量访问设置障碍。
另请注意,您的原始示例使用 Task.Run
,它明确地将工作放在线程池上。这与 async
/await
完全不同,您肯定必须将其视为多线程。
Should I use mutex on possible shared state?
是的。例如,如果您的代码使用 Task.Run
,那么您需要将其视为一个单独的线程。 (请注意,使用 await
,很多更容易完全不与其他线程共享状态 - 如果您可以保持后台任务纯净,它们会更容易工作与)。
If yes, how could I detect what are the shared state objects?
与任何其他类型的多线程代码相同的答案:代码检查。
关于c# - "multi-threadedly"在 async/await 模式下实际上执行了什么代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36690980/