在已经拆分的上下文上调用 await 时是否有开销?
Is there overhead when calling await on already split context?
编辑:我的问题并没有真正意义,因为我误解了任务的工作方式。我已将 stephen cleary 的回答标记为已接受,因为它为我指明了学习错误的方向。
我经常看到这样的代码:
public async Task DoSomething(){
await DoSomethingElse();
await DoSoManyThings();
await DoEverything();
}
现在我看到的是第一个 await 启动第二个线程,returns 控制调用线程。当 await 完成时,将调用第二个 await。现在这是我可能会感到困惑的地方。第二个 await 拆分上下文/创建新线程,另一个线程消失(returns 给调用者)。这有开销吗?如果是这样,多少钱?最好让我的代码如下,以避免无缘无故地创建新线程:
public async Task DoSomething(){
await DoSomethingElse();
DoSoManyThings();
DoEverything();
}
这是一个完整的代码示例,按照要求显示了我的意思。
循环是为了确保等待的代码不会立即完成。两个测试函数的输出相同。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestApplication
{
public class Program
{
static void Main(string[] args)
{
Program test = new Program();
Task firstTest = test.StartMultipleAwaitTest();
firstTest.Wait();
test.StartSingleAwaitTest();
Console.ReadLine();
}
public async Task StartSingleAwaitTest()
{
Console.WriteLine("\nStarting second test");
await FirstTask();
SecondTask();
ThirdTask();
Console.WriteLine("End");
}
public async Task StartMultipleAwaitTest()
{
Console.WriteLine("Start");
await FirstTask();
await SecondTask();
await ThirdTask();
Console.WriteLine("End");
}
public async Task FirstTask()
{
Console.WriteLine("Start First task");
for (int i = 0; i < 10000000; i++) { }
Console.WriteLine("End Firt task");
}
public async Task SecondTask()
{
Console.WriteLine("Start Second task");
for (int i = 0; i < 10000000; i++) { }
Console.WriteLine("End Second task");
}
public async Task ThirdTask()
{
Console.WriteLine("Start Third task");
for (int i = 0; i < 10000000; i++) { }
Console.WriteLine("End Third task");
}
}
}
the first await starts a second thread and returns control to the calling thread.
没有。 await
最强调的是 不 启动第二个线程。我有一个博客 post 描述 what await
does do in detail。
Output is identical for both test functions.
输出相同的原因是因为在这两种情况下,所有函数 运行 都是同步的。注意你的编译器警告;在这种情况下,编译器将对您的 FirstTask
方法(和朋友)发出警告,说明这些方法将 运行 同步。
StartMultipleAwaitTest
测试中实际发生的是,在 await
甚至检查 Task
之前,方法已经 运行 完成。同样,在 StartSingleAwaitTest
测试中,方法也在返回 StartSingleAwaitTest
.
之前同步 运行 完成
更真实的测试(即在异步方法中进行异步工作)将为您提供更真实的结果:
public async Task FirstTask()
{
Console.WriteLine("Start First task");
await Task.Delay(TimeSpan.FromSeconds(2));
Console.WriteLine("End Firt task");
}
public async Task SecondTask()
{
Console.WriteLine("Start Second task");
await Task.Delay(TimeSpan.FromSeconds(3));
Console.WriteLine("End Second task");
}
public async Task ThirdTask()
{
Console.WriteLine("Start Third task");
await Task.Delay(TimeSpan.FromSeconds(2));
Console.WriteLine("End Third task");
}
编辑:我的问题并没有真正意义,因为我误解了任务的工作方式。我已将 stephen cleary 的回答标记为已接受,因为它为我指明了学习错误的方向。
我经常看到这样的代码:
public async Task DoSomething(){
await DoSomethingElse();
await DoSoManyThings();
await DoEverything();
}
现在我看到的是第一个 await 启动第二个线程,returns 控制调用线程。当 await 完成时,将调用第二个 await。现在这是我可能会感到困惑的地方。第二个 await 拆分上下文/创建新线程,另一个线程消失(returns 给调用者)。这有开销吗?如果是这样,多少钱?最好让我的代码如下,以避免无缘无故地创建新线程:
public async Task DoSomething(){
await DoSomethingElse();
DoSoManyThings();
DoEverything();
}
这是一个完整的代码示例,按照要求显示了我的意思。 循环是为了确保等待的代码不会立即完成。两个测试函数的输出相同。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestApplication
{
public class Program
{
static void Main(string[] args)
{
Program test = new Program();
Task firstTest = test.StartMultipleAwaitTest();
firstTest.Wait();
test.StartSingleAwaitTest();
Console.ReadLine();
}
public async Task StartSingleAwaitTest()
{
Console.WriteLine("\nStarting second test");
await FirstTask();
SecondTask();
ThirdTask();
Console.WriteLine("End");
}
public async Task StartMultipleAwaitTest()
{
Console.WriteLine("Start");
await FirstTask();
await SecondTask();
await ThirdTask();
Console.WriteLine("End");
}
public async Task FirstTask()
{
Console.WriteLine("Start First task");
for (int i = 0; i < 10000000; i++) { }
Console.WriteLine("End Firt task");
}
public async Task SecondTask()
{
Console.WriteLine("Start Second task");
for (int i = 0; i < 10000000; i++) { }
Console.WriteLine("End Second task");
}
public async Task ThirdTask()
{
Console.WriteLine("Start Third task");
for (int i = 0; i < 10000000; i++) { }
Console.WriteLine("End Third task");
}
}
}
the first await starts a second thread and returns control to the calling thread.
没有。 await
最强调的是 不 启动第二个线程。我有一个博客 post 描述 what await
does do in detail。
Output is identical for both test functions.
输出相同的原因是因为在这两种情况下,所有函数 运行 都是同步的。注意你的编译器警告;在这种情况下,编译器将对您的 FirstTask
方法(和朋友)发出警告,说明这些方法将 运行 同步。
StartMultipleAwaitTest
测试中实际发生的是,在 await
甚至检查 Task
之前,方法已经 运行 完成。同样,在 StartSingleAwaitTest
测试中,方法也在返回 StartSingleAwaitTest
.
更真实的测试(即在异步方法中进行异步工作)将为您提供更真实的结果:
public async Task FirstTask()
{
Console.WriteLine("Start First task");
await Task.Delay(TimeSpan.FromSeconds(2));
Console.WriteLine("End Firt task");
}
public async Task SecondTask()
{
Console.WriteLine("Start Second task");
await Task.Delay(TimeSpan.FromSeconds(3));
Console.WriteLine("End Second task");
}
public async Task ThirdTask()
{
Console.WriteLine("Start Third task");
await Task.Delay(TimeSpan.FromSeconds(2));
Console.WriteLine("End Third task");
}