一尘不染

C#异步/等待有/没有等待(即发即忘)

c#

我有以下代码:

    static async Task Callee()
    {
        await Task.Delay(1000);
    }

    static async Task Caller()
    {
        Callee(); // #1 fire and forget
        await Callee(); // #2 >1s
        Task.Run(() => Callee()); // #3 fire and forget
        await Task.Run(() => Callee()); // #4 >1s
        Task.Run(async () => await Callee()); // #5 fire and forget
        await Task.Run(async () => await Callee()); // #6 >1s
    }

    static void Main(string[] args)
    {
        var stopWatch = new Stopwatch();
        stopWatch.Start();
        Caller().Wait();
        stopWatch.Stop();
        Console.WriteLine($"Elapsed: {stopWatch.ElapsedMilliseconds}");
        Console.ReadKey();
    }

#1以最简单的方式解雇。#2只是等待。有趣的东西从#3开始。通话背后的深入逻辑是什么?

我知道在ASP.NET中使用fire’n’forget作为警告的指向这里。我之所以这么问,是因为我们将应用程序移到了不再可以使用的服务结构上,HostingEnvironment.QueueBackgroundWorkItem(async cancellationToken => await LongMethodAsync());建议将其替换为Task.Run

我看到Task.Run运行了一个新线程,那么#3和#5之间会有什么区别?


阅读 451

收藏
2020-05-19

共1个答案

一尘不染

我之所以这么问,是因为我们将应用程序移至服务结构,因此我们不再可以使用HostingEnvironment.QueueBackgroundWorkItem(async
cancelleToken => await LongMethodAsync());。建议是简单地将其替换为Task.Run。

那是个坏建议。您应该使用一个独立的后台进程,该进程通过队列与Web前端分开

通话背后的深入逻辑是什么?

  1. 在当前线程上启动异步方法。忽略所有结果(包括异常)。
  2. 在当前线程上启动异步方法。异步等待它完成。这是调用异步代码的标准方法。
  3. 在线程池线程上启动异步方法。忽略所有结果(包括异常)。
  4. 在线程池线程上启动异步方法。异步等待它完成。
  5. 与#3完全相同。
  6. 与#4完全相同。
2020-05-19