【问题标题】:Proper way to "fire and forget" async Tasks or run it in background\"fire and forget\" 异步任务或在后台运行它的正确方法
【发布时间】:2023-01-14 01:31:43
【问题描述】:

我需要运行一些异步任务,结果我永远不会在任何地方使用,我不在乎它什么时候完成。

例如,我可能需要我的 Discord 客户端响应如下命令:

// .command
await StartLongAsyncTaskThatMayTakeForeverToCompleteAndSay("I'm late");
await Context.Message.ReplyAsync("Immediately say hi"));
// => "Immediately say hi"
// *few seconds later*
// => "I'm late"

我应该使用:await StartLongAsyncTask().ConfigureAwait(false);_ = StartLongAsyncTask(); 还是应该使用Task.Run(() => {} );,有什么区别?

【问题讨论】:

    标签: c# .net asynchronous


    【解决方案1】:

    好吧,您绝对不想等待您的长时间运行的任务然后回复,您似乎想立即回复并让长时间运行的任务顺其自然:

    // .command
    _ = StartLongAsyncTaskThatMayTakeForeverToCompleteAndSay("I'm late");
    await Context.Message.ReplyAsync("Immediately say hi"));
    // => "Immediately say hi"
    // *few seconds later*
    // => "I'm late"
    

    有什么区别

    列表中最后两个选项(我认为第一个选项很明显)之间的区别是 Task.Run 版本在线程池上运行异步函数,对于任何行为良好的 API,您永远不应该手动执行此操作,而简单地调用任务在您自己的线程上运行它(或至少启动它)(这对于 I/O 绑定操作来说非常好)。

    【讨论】:

      【解决方案2】:

      这在很大程度上取决于 StartLongAsyncTaskThatMayTakeForeverToCompleteAndSay 是什么和上下文,例如在某些情况下,将调用结果分配给任务变量并在第二次调用后等待它就可以了:

      var task = StartLongAsyncTaskThatMayTakeForeverToCompleteAndSay("I'm late");
      await Context.Message.ReplyAsync("Immediately say hi"));
      await task;
      

      要不就:

      await Task.WhenAll(StartLongAsyncTaskThatMayTakeForeverToCompleteAndSay("I'm late"), 
          Context.Message.ReplyAsync("Immediately say hi")));
      

      对于两者之间的差异 - 请参阅Why should I prefer single 'await Task.WhenAll' over multiple awaits?

      【讨论】:

        猜你喜欢
        • 2011-02-07
        • 2021-02-13
        • 2014-05-16
        • 2020-03-21
        • 2019-07-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多