【问题标题】:Why is my async method finishing before the next line in the caller method is executed?为什么我的异步方法在调用者方法的下一行执行之前完成?
【发布时间】:2019-11-27 15:31:12
【问题描述】:

考虑以下方法:

        public static void Main(string[] args)
        {
            Stopwatch stopwatch = new Stopwatch();

            // Begin timing.
            stopwatch.Start();

            Task task =  dosomething(stopwatch);
            Console.WriteLine("Waiting for async to finish {0}", stopwatch.Elapsed);
            task.Wait();
            Console.WriteLine("After wait {0}",stopwatch.Elapsed);


            // Stop timing.
            stopwatch.Stop();

            // Write result.
        }

        public static async Task dosomething(Stopwatch stopwatch)
        {
            Console.WriteLine("Started async", stopwatch.Elapsed);
            await dos();
            Console.WriteLine("Ended async", stopwatch.Elapsed);
        }

        public static async Task dos()  
        {
            Thread.Sleep(5000);
            Thread.Sleep(1000);

        }
    }
}

我本来希望输出是这样的:

开始异步

等待异步完成

结束异步

等待之后

但我得到以下输出

开始异步

结束异步

等待异步完成 00:00:06.0990283

等待 00:00:06.0992659

我认为当您等待方法完成时,控制权会返回给调用者。因此,应该在“结束异步”之前调用“等待异步完成”。

【问题讨论】:

  • 不要忽略警告。编译器应该已经提醒您 dos 没有 await 任何东西,因此将同步完成。使用await Task.Delay,而不是Thread.Sleepasync not 的意思是“为我在后台运行它”,它的意思是“允许我使用 await 语法来编写异步代码,就好像它是同步的一样”。您仍然需要提供实际的异步代码。
  • 微软有一些写得很好的关于异步编程的文章值得一读。从这里开始:Asynchronous programming with async and await.
  • 我在 dotnetfiddle.com 上运行它没有看到任何警告 >.

标签: c# async-await


【解决方案1】:

Thread.Sleep异步的。因此,线程将被阻塞,您的代码将同步执行。如果您将Thread.Sleepawait Task.Delay 交换,您将获得预期的输出。

有关编译器应该发出的警告 (CS1998) 的更多信息,请参阅this question。引用斯蒂芬·克利里的话:

一个非常常见的异步新手错误是假设异步意味着“使此方法异步”。这通常与“异步”意味着“在后台线程上运行”的假设配对,但有时它只是“魔术”的假设。

因此,警告明确指出代码将运行 同步。

【讨论】:

    【解决方案2】:

    正如其他答案中提到的,Task.Delay() 有效,而且您不需要创建任务对象引用然后调用它。我刚刚在 doSomething 上调用了 .Wait() ,它对我有用。

    这是我的解决方案

    static void Main(string[] args)
        {
    
            Stopwatch stopwatch = new Stopwatch();
            // Begin timing.
            stopwatch.Start();
            Console.WriteLine("Waiting for async to finish {0}", stopwatch.Elapsed);
            dosomething(stopwatch).Wait();
            Console.WriteLine("After wait {0}", stopwatch.Elapsed);
            // Stop timing.
            stopwatch.Stop();
    
            // Write result.
            Console.ReadLine();
        }
    
        public static async Task dosomething(Stopwatch stopwatch)
        {
            Console.WriteLine("Started async", stopwatch.Elapsed);
            await Task.Delay(6000);
            Console.WriteLine("Ended async", stopwatch.Elapsed);
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-29
      • 1970-01-01
      • 1970-01-01
      • 2021-11-28
      • 2017-06-07
      • 2023-03-12
      相关资源
      最近更新 更多