异步方法未并行运行 [英] Async method not running in parallel
问题描述
在以下代码的B方法中,代码Trace.TraceInformation("B-Started");永远不会被打电话.
In the following code, in the B method, the code Trace.TraceInformation("B - Started"); never gets called.
该方法应该并行运行吗?
Should the method be running in parallel?
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
private static async Task A()
{
for (;;)
{
}
}
private static async Task B()
{
Trace.TraceInformation("B - Started");
}
static void Main(string[] args)
{
var tasks = new List<Task> { A(), B() };
Task.WaitAll(tasks.ToArray());
}
}
}
推荐答案
简短答案
否,当您编写了两个async
方法时,它们确实不是并行运行的.将await Task.Yield();
添加到您的第一个方法中(例如,在循环内)将允许他们这样做,但是有更多更合理,更直接的方法,这很大程度上取决于您的实际需要(在单个步骤上交错执行)线程?实际上是在多个线程上并行执行?).
No, as you wrote your two async
methods, they are indeed not running in parallel. Adding await Task.Yield();
to your first method (e.g. inside the loop) would allow them to do so, but there are more reasonable and straightforward methods, highly depending on what you actually need (interleaved execution on a single thread? Actual parallel execution on multiple threads?).
好答案
首先,将函数声明为async
并不会使它们固有地异步运行.它相当简化了语法,在这里可以了解更多有关概念的信息:异步编程使用Async和Await
First of all, declaring functions as async
does not inherently make them run asynchronously or something. It rather simplifies the syntax to do so - read more about the concepts here: Asynchronous Programming with Async and Await
实际上,A
根本不是异步的,因为其方法体内没有单个await
.直到首次使用await
的指令都像常规方法一样同步运行.
Effectively A
is not asynchronous at all, as there is not a single await
inside its method body. Instructions up to the first use of await
run synchronously like a regular method would.
此后,您await
的对象确定接下来将发生什么,即其余方法在其中运行的上下文.
From then on, the object that you await
determines what happens next, i.e. the context that the remaining method runs in.
要强制在另一个线程上执行任务,请使用Task.Run
或类似的命令.
To force execution of a task to happen on another thread, use Task.Run
or similar.
在这种情况下,添加await Task.Yield()
可以解决问题,因为当前的同步上下文是null
,而这恰好确实导致任务调度程序(应该为ThreadPoolTaskScheduler
)在线程池线程上执行其余指令-某些环境或配置可能会导致您只有其中之一,因此仍然无法并行运行.
In this scenario, adding await Task.Yield()
does the trick since the current synchronization context is null
and this happens to indeed cause the task scheduler (should be ThreadPoolTaskScheduler
) to execute the remaining instuctions on a thread-pool thread - some environment or configuration might cause you to only have one of them, so things would still not run in parallel.
摘要
故事的寓意是:注意两个概念之间的差异:
The moral of the story is: Be aware of the differences between two concepts:
- 并发(通过合理使用
async
/await
启用)和 - 并行性(仅当并发任务按正确的方式排定 时发生,或者如果您使用
Task.Run
,Thread
等强制实施并行化,则这种情况会发生.反正async
的使用是完全无关的
- concurrency (which is enabled by using
async
/await
reasonably) and - parallelism (which only happens when concurrent tasks get scheduled the right way or if you enforce it using
Task.Run
,Thread
, etc. in which case the use ofasync
is completely irrelevant anyway)
这篇关于异步方法未并行运行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!