Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 这两个等待电话有什么区别_C#_.net_Async Await - Fatal编程技术网

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中,您等待每个任务完成,然后再开始下一个任务。

A
Task
在您调用该方法后立即开始运行。您正在调用
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编译

    您是否尝试过将第一个选项与第二个选项切换,以了解其测量结果

    如果你看一下,你会发现没有显著的差异


    为了有效地衡量性能,您需要在第一个代码块中启动每个任务并等待其完成,然后再移动到下一个任务并执行相同的操作,它们按顺序运行,其中下一个任务仅在前一个任务完成后才开始。把那个街区想象成接力赛。在第二段代码中,首先启动每个任务,然后等待它们完成