Async/Await 单 thread/some 线程
Async/Await single thread/some threads
我需要一些关于正确使用 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("---------------");
}
}
如您所见,两种方法的行为是不同的。实践中很容易出错。所以我需要一个 "thumb rule".
真男人更新拜托,运行代码。请解释为什么 Parallel() 运行s 比 NonParallel() 快。
在没有 await
的情况下调用 GetTaskAsync
时,您实际上得到了一个任务,其中包含要执行的方法(即 GetTaskAsync
)。但是当调用 await GetTaskAsync
时, 执行暂停,直到方法执行完毕,然后你得到结果。
让我说得更清楚:
var task = GetTaskAsync(2000);
此处,任务类型为Task<string>
。
var result = await GetTaskAsync(2000);
这里的结果是 string
.
类型
所以要解决您的第一个问题:何时等待您的任务实际上取决于您的执行流程。
现在,至于为什么 Parallel()
更快,我建议您阅读此 article(所有内容都很有趣,但对于您的具体示例,您可以跳转到 Tasks return"hot").
现在让我们分解一下:
The await
keyword serves to halt the code until the task is completed,
but doesn't actually start it.
在您的示例中,NotParallel()
将花费更长的时间,因为您的任务按顺序执行,一个接一个。如文章所述:
This is due to the tasks being awaited inline.
然而在Parallel()
中...
the tasks now run in parallel. This is due to the fact that all [tasks]
are started before all [tasks] are subsequently awaited, again, because
they return hot.
关于 'hot' 个任务
我建议您阅读以下内容:Task-based Asynchronous Pattern (TAP)
任务状态部分在这里很有趣,可以了解冷任务和热任务的概念:
Tasks that are created by the public Task constructors are referred to as cold tasks, because they begin their life cycle in the non-scheduled Created state and are scheduled only when Start is called on these instances.
All other tasks begin their life cycle in a hot state, which means that the asynchronous operations they represent have already been initiated
我邀请您广泛阅读 async/await
和 Tasks
。除了我上面提供的资源之外,这里还有一些资源:
Asynchronous Programming in C# 5.0 part two: Whence await?
我需要一些关于正确使用 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("---------------");
}
}
如您所见,两种方法的行为是不同的。实践中很容易出错。所以我需要一个 "thumb rule".
真男人更新拜托,运行代码。请解释为什么 Parallel() 运行s 比 NonParallel() 快。
在没有 await
的情况下调用 GetTaskAsync
时,您实际上得到了一个任务,其中包含要执行的方法(即 GetTaskAsync
)。但是当调用 await GetTaskAsync
时, 执行暂停,直到方法执行完毕,然后你得到结果。
让我说得更清楚:
var task = GetTaskAsync(2000);
此处,任务类型为Task<string>
。
var result = await GetTaskAsync(2000);
这里的结果是 string
.
所以要解决您的第一个问题:何时等待您的任务实际上取决于您的执行流程。
现在,至于为什么 Parallel()
更快,我建议您阅读此 article(所有内容都很有趣,但对于您的具体示例,您可以跳转到 Tasks return"hot").
现在让我们分解一下:
The
await
keyword serves to halt the code until the task is completed, but doesn't actually start it.
在您的示例中,NotParallel()
将花费更长的时间,因为您的任务按顺序执行,一个接一个。如文章所述:
This is due to the tasks being awaited inline.
然而在Parallel()
中...
the tasks now run in parallel. This is due to the fact that all [tasks] are started before all [tasks] are subsequently awaited, again, because they return hot.
关于 'hot' 个任务
我建议您阅读以下内容:Task-based Asynchronous Pattern (TAP)
任务状态部分在这里很有趣,可以了解冷任务和热任务的概念:
Tasks that are created by the public Task constructors are referred to as cold tasks, because they begin their life cycle in the non-scheduled Created state and are scheduled only when Start is called on these instances.
All other tasks begin their life cycle in a hot state, which means that the asynchronous operations they represent have already been initiated
我邀请您广泛阅读 async/await
和 Tasks
。除了我上面提供的资源之外,这里还有一些资源:
Asynchronous Programming in C# 5.0 part two: Whence await?