【问题标题】:fire and forget an async Task method sometimes not invoke触发并忘记异步任务方法有时不会调用
【发布时间】:2014-05-05 02:57:01
【问题描述】:

我有一个异步方法:

public async Task DoSomethingAsync(){
    ...
    await ...
    await ...
    ....
    return await SaveAsync();
}

在大多数情况下,我通过以下方式调用此方法:

await DoSomethingAsync()

此调用按预期工作。但是在某个地方,我需要将此方法称为火而忘记:

public void OtherMethod()
{
    ...
    DoSomethingAsync(); //fire and forget here
}

在这种情况下,有时任务DoSomethingAsync() 运行并完成,但有时任务从未被调用(或在DoSomethingAsync() 中调用一些awaits 但从未完成最后一个await SaveAsync();)。

我正在尝试确保任务将通过这些代码以火和忘记的方式调用:

public void OtherMethod()
{
    ...
    Task.Factory.StartNew(() =>
    {
        await DoSomethingAsync();
    }); //fire and forget again here
}

但是,这并不像预期的那样工作。所以我的问题是:

  1. 如何在没有await 的情况下调用DoSomethingAsync() 将始终运行并完成? (我不关心 AppDomain 重启/崩溃的情况)

  2. 1234563完成(忽略 AppDomain 重启/崩溃的情况),如果是,距离调用多长时间(如果任务将在 10 分钟后被调用,我认为我不会高兴)?

【问题讨论】:

    标签: c# .net asp.net-mvc async-await fire-and-forget


    【解决方案1】:

    等待应该工作正常,所以这里可能有其他事情正在等待你的一个或多个方法。有几种可能:

    1. 您的某个方法的某处出现了死锁,导致它无法完成并阻止等待恢复。
    2. 您的所有线程池线程都因某种原因而阻塞,从而阻止待处理的任务运行。
    3. 您正在同步上下文中运行 async 方法,但有东西阻碍了上下文,阻止它运行已调度的回调。通常情况下,上下文是 UI 线程,这通常很明显,因为它会锁定您的应用程序 UI。

    如果您可以附加 VS 调试器并观察发生的情况,请尝试暂停并查看 Parallel Stacks 视图。这应该有助于缩小要考虑的可能性。


    正如斯蒂芬指出的那样,当您将其称为“即发即弃”时,也可能发生异常。如果您还没有,请确保您处理 TaskScheduler.UnobservedTaskException 以记录任何此类事件。请注意,这是从终结器调用的,因此调用它的时间是不确定的。这会使调试变得棘手,因为事件可能要到比导致异常的实际事件晚得多时才会触发。因此,我建议遵循 Stephen 的建议并将任务保存以等待或稍后在其他地方等待。

    【讨论】:

      【解决方案2】:

      您可能在 DoSomethingAsync 的某个地方遇到了异常,您无法观察到该异常,因为您忽略了该任务。这正是您要求的行为,因为您是在告诉代码“忘记”任务。

      要观察异常,您不能“忘记”任务:

      public Task OtherMethodAsync()
      {
        ...
        return DoSomethingAsync();
      }
      

      在某些时候,await(或Wait)返回的任务。这就是您知道任务将运行和完成的方式。

      【讨论】:

      • 啊,我错过了异常情况;我假设 OP 正在挂钩 TaskScheduler.UnobservedTaskException,但这不一定是一个有效的假设。
      • hmm,实际上,DoSomethingAsync() 的主体由try catch 包裹,如果发生异常会记录。但我没有看到任何异常产生
      • @langtu:在这种情况下,这可能是 DanBryant 建议的死锁情况。
      【解决方案3】:

      ASP.NET 通常不允许从请求中启动即发即弃(异步无效)操作。请参阅 https://stackoverflow.com/a/22484832/59641 以进一步了解此行为和一些潜在的解决方法。

      【讨论】:

        猜你喜欢
        • 2016-06-21
        • 1970-01-01
        • 2020-04-25
        • 2014-12-06
        • 2020-07-01
        • 2010-09-14
        • 2013-09-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多