【问题标题】:Task.Run vs. ContinueWith in ASP.NET MVCASP.NET MVC 中的 Task.Run 与 ContinueWith
【发布时间】:2014-05-29 13:24:23
【问题描述】:

在我的 ASP.NET MVC 4 应用程序中,假设我有一些 async 方法:

async Task DoSomeBackgroundWork()
{
   // Fake it
   await Task.Delay(5000);
}

现在,可以这样调用这个方法:

Task.Run(async () => 
{
  await DoSomeBackgroundWork();
  Debug.WriteLine("Background work finished");
});

或者这个:

DoSomeBackgroundWork()
  .ContinueWith(t => Debug.WriteLine("Background work finished"));

请注意,在这两个版本中,调用者都不会等待后台任务完成。这只是一发不可收拾。

虽然两个版本在常规 .NET 应用程序上的工作方式相同(此处忽略异常处理),但在 MVC 应用程序上,当从 MVC 控制器方法调用代码时Debug.WriteLine 仅在Task.Run 版本 - 但不在 ContinueWith 版本中。

谁能解释为什么这两个版本在 MVC 控制器方法中调用时工作方式不同?

【问题讨论】:

  • 对我也很好。在 .NET4.5 Web 应用程序中弹出Global.asax
  • @Noseratio 它实际上目前看起来是这样的。
  • 添加Debug.WriteLine(new { SynchronizationContext.Current }); 内外DoSomeBackgroundWork,无处不在。你在任何地方看到AspNetSynchronizationContextLegacyAspNetSynchronizationContext 吗? (具体是什么,在哪里?)
  • @SriramSakthivel 这就是重点!例如,在控制台中它工作正常。但不是在 MVC 中。
  • @Noseratio 在控制器方法(调用者)内部,上下文为AspNetSynchronizationContext。在DoSomeBackgroundWork()内部,直接从控制器方法调用时也是AspNetSynchronizationContext;当从Task.Run() 中调用DoSomeBackgroundWork() 时,它是null

标签: c# asp.net asp.net-mvc task-parallel-library async-await


【解决方案1】:

这可能是您的网络应用程序所特有的,所以我只能推测,但这是我的想法:

  • 如果你这样做,它应该可以工作:

    DoSomeBackgroundWork()
        .ContinueWith(t => Debug.WriteLine("Background work finished"), 
            TaskContinuationOptions.ExecuteSynchronously);
    

    这将更接近Task.Run 版本,其中延续同步运行。

  • 就在您直接从控制器方法调用DoSomeBackgroundWork 之前,添加以下内容:

    Debug.WriteLine(new { TaskScheduler.Current });
    

    如果输出不是ThreadPoolTaskScheduler,我也许可以进一步解释这种行为(因为我刚刚处理了一个有点相关的问题here)。

顺便说一句,像这样在 ASP.NET 中使用即发即弃真的不是一个好主意,SO 讨论这个问题时有很多问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-03
    • 1970-01-01
    • 1970-01-01
    • 2016-03-04
    • 2015-07-08
    • 2010-10-21
    相关资源
    最近更新 更多