c# - 在已经拆分的上下文上调用 await 时是否有开销?

标签 c# multithreading asynchronous async-await overhead

编辑:我的问题并没有真正意义,因为我误解了任务的工作方式。我已将 stephen cleary 的回答标记为已接受,因为它为我指明了学习错误的方向。

我经常看到这样的代码:

public async Task DoSomething(){
     await DoSomethingElse();
     await DoSoManyThings();
     await DoEverything();
}

现在我看到的是第一个 await 启动第二个线程并将控制返回给调用线程。当 await 完成时,将调用第二个 await。现在这是我可能会感到困惑的地方。第二个 await 拆分上下文/创建新线程,另一个线程消失(返回调用者)。这有开销吗?如果是这样,多少钱?最好让我的代码如下,以避免无缘无故地创建新线程:

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 最强调启动第二个线程。我有一篇博文描述 what await does do in detail .

Output is identical for both test functions.

输出相同的原因是因为在这两种情况下,所有函数都同步运行。注意你的编译器警告;在这种情况下,编译器将针对您的 FirstTask 方法(和 friend )向您发出警告,声明这些方法将同步运行。

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");
}

关于c# - 在已经拆分的上下文上调用 await 时是否有开销?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33862704/

相关文章:

java - 如何在 Android 上的 Java 中每两秒执行一次函数?

c# - 正则表达式匹配文件路径字符串的数字结尾

c# - 帕斯卡三角函数

multithreading - “XORL AX, AX”如何用作内存屏障? [复制]

multithreading - 类级属性或变量是线程安全的

javascript - 在 Parse.com 的 Cloud 代码中,异步代码为 for 循环中的变量提供了错误的值

ios - 将 GCD 与也进行异步调用的代码一起使用是否安全

javascript - 如何从 promise 中获取值(value)。回调返回未定义

c# - 在c#中从数据库生成脚本

c# - Moq 具有匿名类型的函数