C# 这两个等待电话有什么区别
我有以下代码:C# 这两个等待电话有什么区别,c#,.net,async-await,C#,.net,Async Await,我有以下代码: async Task Main() { Stopwatch sw = new Stopwatch(); // Variante 1 sw.Start(); var m1 = await Task1(); var m2 = await Task2(); var m3 = await Task3(); Console.WriteLine(m1); Console.WriteLine(m2); Console.W
async Task Main()
{
Stopwatch sw = new Stopwatch();
// Variante 1
sw.Start();
var m1 = await Task1();
var m2 = await Task2();
var m3 = await Task3();
Console.WriteLine(m1);
Console.WriteLine(m2);
Console.WriteLine(m3);
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
// Variante 2
sw.Restart();
var t1 = Task1();
var t2 = Task2();
var t3 = Task3();
m1 = await t1;
m2 = await t2;
m3 = await t3;
Console.WriteLine(m1);
Console.WriteLine(m2);
Console.WriteLine(m3);
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
}
// Define other methods, classes and namespaces here
public async Task<string> Task1()
{
await Task.Delay(5000);
return "Task1 ready";
}
public async Task<string> Task2()
{
await Task.Delay(5000);
return "Task2 ready";
}
public async Task<string> Task3()
{
await Task.Delay(5000);
return "Task3 ready";
}
async Task Main()
{
秒表sw=新秒表();
//方差1
sw.Start();
var m1=等待任务1();
var m2=等待任务2();
var m3=等待任务3();
控制台写入线(m1);
控制台写入线(m2);
控制台写入线(m3);
sw.Stop();
控制台写入线(软件延迟毫秒);
//方差2
sw.Restart();
var t1=Task1();
var t2=Task2();
var t3=Task3();
m1=等待t1;
m2=等待t2;
m3=等待t3;
控制台写入线(m1);
控制台写入线(m2);
控制台写入线(m3);
sw.Stop();
控制台写入线(软件延迟毫秒);
}
//在此处定义其他方法、类和名称空间
公共异步任务Task1()
{
等待任务。延迟(5000);
返回“Task1就绪”;
}
公共异步任务Task2()
{
等待任务。延迟(5000);
返回“Task2就绪”;
}
公共异步任务Task3()
{
等待任务。延迟(5000);
返回“Task3就绪”;
}
第一部分的结果是近15000毫秒,第二部分是5000毫秒,但我不明白为什么
在第一部分中,我等待一个异步方法返回一个任务,在第二部分中,我得到这个任务并等待该任务
我遗漏了什么?在变体2中,在调用
等待之前,所有三个任务都已启动。在变体1中,您等待每个任务完成,然后再开始下一个任务。ATask
在您调用该方法后立即开始运行。您正在调用Task1
、Task2
和Task3
,而不等待它们中的任何一个,因此它们都开始同时运行
在第二部分中,您正在调用Task1
,然后等待它,然后再调用Task2
和Task3
。这意味着Task2
在Task1
完成之前不会启动,Task3
在Task2
完成之前不会启动。它们一个接一个地运行,延长了总运行时间。在第一个代码块中,您启动每个任务并等待它完成,然后再移动到下一个任务并执行相同的操作,它们按顺序运行,其中下一个任务仅在前一个任务完成后启动。把这想象成一场接力赛,每位参赛者必须等待前一位参赛者完成后才能开始比赛
在第二段代码中,首先启动3个任务中的每一个,然后等待它们逐一完成。它们并行运行,因为您几乎同时启动它们。把这想象成一场比赛,每个人都在同一时间开始,然后等待他们完成。其他答案部分正确,但我想写下自己的答案来澄清一些问题
这些任务不是并行启动的。
严格地说,“并行”意味着同时计算两行代码。这在这里不会发生
每个异步方法开始时都是同步运行的。当await
对一个不完整的任务执行操作时(例如,当一个I/O请求启动时),这种神奇就会发生。此时,该方法返回其自己未完成的任务
,并计划稍后继续该方法
执行此操作时:
var t1 = Task1();
var t2 = Task2();
var t3 = Task3();
var m1 = await Task1();
var m2 = await Task2();
var m3 = await Task3();
情况就是这样:
Task1
开始执行
在第一次等待时,Task1
返回一个Task
Task2
开始执行
在第一次等待时,Task2
返回一个Task
Task3
开始执行
在第一次等待时,Task3
返回一个Task
因此,使此运行更快的原因是,您的代码在Task1
等待响应以启动Task2
中的请求时使用了时间
根据具体情况,这些任务的连续性可能并行运行
在存在同步上下文(如ASP.NET)的情况下,continuations必须返回到相同的上下文,并且任何内容都不会并行运行。这意味着在该上下文下运行nothing Other之前,Task1
的执行不会继续。在代码中,这种情况发生在:
m1 = await t1;
只有在该行之后,当前上下文才被释放,Task1
的延续才能在该上下文中运行,完成后,wait t1
之后的所有内容都会被放在“待办事项”列表中完成
如果在没有同步上下文(like)的情况下运行,或者指定.ConfigureAwait(false)
告诉它不需要它返回到相同的上下文,则任务的继续将在线程池线程上运行。这意味着所有三个任务的延续可以在不同的线程上并行运行。如果发生这种情况,那么当您点击等待t1
时,它可能已经完成了
如果您这样做:
var t1 = Task1();
var t2 = Task2();
var t3 = Task3();
var m1 = await Task1();
var m2 = await Task2();
var m3 = await Task3();
您要等到任务1
完全完成后才开始执行任务2
。根据您的应用程序,这仍然有好处。例如,在ASP.NET中,它释放线程以供其他一些不相关的请求使用。在桌面应用程序中,它可以释放UI线程来响应用户输入。这里的问题是,您的度量中包含了JIT编译
您是否尝试过将第一个选项与第二个选项切换,以了解其测量结果
如果你看一下,你会发现没有显著的差异
为了有效地衡量性能,您需要在第一个代码块中启动每个任务并等待其完成,然后再移动到下一个任务并执行相同的操作,它们按顺序运行,其中下一个任务仅在前一个任务完成后才开始。把那个街区想象成接力赛。在第二段代码中,首先启动每个任务,然后等待它们完成