在async/await模式中"多线程"实际执行了什么代码?

ded*_*cos 3 c# multithreading asynchronous async-await

在这段代码中:

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!");
}
Run Code Online (Sandbox Code Playgroud)

如果调用ButtonClick,上述哪些方法实际上是在async/await生成的底线程池中并行执行的?

我的意思是,对于使用async/await的竞争条件,我应该关注什么?所有异步方法都必须在同一个调用者的线程中执行?我应该在可能的共享状态上使用互斥吗?如果是,我怎么能检测到共享状态对象是什么?

Ste*_*ary 6

如果调用ButtonClick,上述哪些方法实际上是在async/await生成的底线程池中并行执行的?

只有Console.WriteLine在内Task.Run.

我的意思是,对于使用async/await的竞争条件,我应该关注什么?

我建议你先阅读我的async介绍,这解释了await实际的工作原理.

总之,async方法通常以串行异步方式编写.以此代码为例:

CodeBeforeAwait();
await SomeOtherMethodAsync();
CodeAfterAwait();
Run Code Online (Sandbox Code Playgroud)

你总是可以说CodeBeforeAwait先执行完成,然后SomeOtherMethodAsync调用.然后我们的方法将(异步)等待SomeOtherMethodAsync完成,并且只有在此之后才会CodeAfterAwait被调用.

所以它是串行异步的.它以串行的方式执行,就像你期望的那样,但也在该流程中使用异步点(the await).

现在,你不能CodeBeforeAwait并且CodeAfterAwait将在同一个线程中执行,至少在没有更多上下文的情况下.await默认情况下将恢复当前SynchronizationContext(TaskScheduler如果没有SyncCtx 则恢复当前).因此,如果上面的示例方法在UI线程中执行,那么您将知道CodeBeforeAwait并且CodeAfterAwait将在UI线程上执行.但是,如果它是在没有上下文的情况下执行的(即,从后台线程或Console主线程执行),则CodeAfterAwait可以在不同的线程上运行.

请注意,即使方法的某些部分在不同的线程上运行,运行时也会在继续该方法之前设置任何障碍,因此不需要屏蔽变量访问.

另请注意,您的原始示例使用了Task.Run,它明确地将工作放在线程池上.这与async/ 完全不同await,你肯定必须将其视为多线程.

我应该在可能的共享状态上使用互斥吗?

是.例如,如果您的代码使用Task.Run,那么您需要将其视为单独的线程.(请注意,使用await,这是一个很多更容易不与其他线程在所有共享状态-如果你能保持你的后台任务纯洁,所以他们可以很容易与工作).

如果是,我怎么能检测到共享状态对象是什么?

与任何其他类型的多线程代码相同的答案:代码检查.