在此代码中:
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生成的较低线程池中并行执行?
我的意思是,我对使用异步/等待的竞争条件应该有什么关注?所有异步方法都必须在同一调用者的线程中执行吗?我应该在可能的共享状态上使用互斥锁吗?如果是,我如何检测共享状态对象是什么?
如果调用ButtonClick,上述哪些方法实际上在async / await生成的较低线程池中并行执行?
仅Console.WriteLine
在内Task.Run
。
我的意思是,我对使用异步/等待的竞争条件应该有什么关注?
我建议您先阅读我的async
介绍,它介绍了await
实际的工作方式。
总之,async
方法通常以串行异步方式编写。以下面的代码为例:
CodeBeforeAwait();
await SomeOtherMethodAsync();
CodeAfterAwait();
您总是可以说CodeBeforeAwait
先执行到完成,然后再SomeOtherMethodAsync
调用。然后我们的方法将(异步)等待SomeOtherMethodAsync
完成,只有在此之后才会CodeAfterAwait
被调用。
因此它是串行异步的。就像您期望的那样,它以串行方式执行,但是在该流中有一个异步点(await
)。
现在,您不能这么说,CodeBeforeAwait
并且CodeAfterAwait
将在同一线程中执行,至少在没有更多上下文的情况下如此。await
默认情况下将在当前SynchronizationContext
(TaskScheduler
如果没有SyncCtx ,则在当前)中恢复。因此,如果上面的示例方法是在UI线程中执行的,那么您将知道这一点,CodeBeforeAwait
并且CodeAfterAwait
都将在UI线程上执行。但是,如果执行时没有上下文(即从后台线程或控制台主线程),则CodeAfterAwait
可能在其他线程上运行。
请注意,即使方法的某些部分在不同的线程上运行,运行时也会在继续执行该方法之前将所有的障碍放置在适当的位置,因此无需在变量访问方面设障碍。
还要注意,您的原始示例使用Task.Run
,将工作明确地放在线程池上。这与async
/完全不同await
,您绝对必须将其视为多线程。
我应该在可能的共享状态上使用互斥锁吗?
是。例如,如果您的代码使用Task.Run
,则需要将其视为一个单独的线程。(注:在await
,这是一个很多更容易不共享状态都与其他线程-如果你能保持你的后台任务纯洁,他们更容易与工作)。
如果是,我如何检测共享状态对象是什么?
与任何其他类型的多线程代码相同的答案:代码检查。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句