我需要一些关于正确使用await的规则。在.net core c#7.2中运行此代码:
static class Program
{
static async Task<string> GetTaskAsync(int timeout)
{
Console.WriteLine("Task Thread: " + Thread.CurrentThread.ManagedThreadId);
await Task.Delay(timeout);
return timeout.ToString();
}
static async Task Main()
{
Console.WriteLine("Main Thread: " + Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("Should be greater than 5000");
await Watch(NotParallel);
Console.WriteLine("Should be less than 5000");
await Watch(Parallel);
}
public static async Task Parallel()
{
var res1 = GetTaskAsync(2000);
var res2 = GetTaskAsync(3000);
Console.WriteLine("result: " + await res1 + await res2);
}
public static async Task NotParallel()
{
var res1 = await GetTaskAsync(2000);
var res2 = await GetTaskAsync(3000);
Console.WriteLine("result: " + res1 + res2);
}
private static async Task Watch(Func<Task> func) {
var sw = new Stopwatch();
sw.Start();
await func?.Invoke();
sw.Stop();
Console.WriteLine("Elapsed: " + sw.ElapsedMilliseconds);
Console.WriteLine("---------------");
}
}
大家可以看到两种方法的行为不同。在实践中容易出错。所以我需要一个&#34;拇指规则&#34;。
真人更新请运行代码。并解释为什么Parallel()比NonParallel()运行得更快。
答案 0 :(得分:3)
在没有GetTaskAsync
的情况下调用await
时,你实际上得到一个任务,其中包含要执行的方法(即GetTaskAsync
)。但是当调用await GetTaskAsync
时,执行暂停,直到方法执行完毕,然后你得到结果。
让我更清楚一点:
var task = GetTaskAsync(2000);
此处,任务类型为Task<string>
。
var result = await GetTaskAsync(2000);
此处的结果是string
类型。
因此,要解决您的第一次询问:何时等待您的任务实际上取决于您的执行流程。
现在,为什么Parallel()
更快,我建议您阅读此article(一切都很有趣,但对于您的具体示例,您可以跳转到任务返回“热门” )。
现在让我们分解一下:
await
关键字用于暂停代码,直到任务完成, 但实际上并没有启动它。
在您的示例中,NotParallel()
将花费更长的时间,因为您的任务依次执行,一个接一个地执行。正如文章所解释的那样:
这是由于正在等待内联任务。
然而在Parallel()
......
任务现在并行运行。这是因为所有[任务] 在所有[任务]随后等待之前开始,因为 他们回来了。
我建议您阅读以下内容:Task-based Asynchronous Pattern (TAP)
任务状态部分非常感兴趣,可以了解冷热任务的概念:
公共任务构造函数创建的任务称为冷任务,因为它们在非调度的创建状态下开始其生命周期,并且仅在对这些实例调用Start时进行调度。
所有其他任务在热状态下开始其生命周期,这意味着它们所代表的异步操作已经启动
我邀请您详细阅读async/await
和Tasks
。除了上面提供的资源之外,还有一些资源:
Asynchronous Programming in C# 5.0 part two: Whence await?