ASP.NET MVC中的Task.Run与ContinueWith

时间:2014-04-15 09:21:21

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

在我的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控制器方法中调用时,有没有人可以解释为什么这两个版本的工作方式不同?

1 个答案:

答案 0 :(得分:5)

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

  • 如果您这样做,它应该有效:

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

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

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

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

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

BTW,在ASP.NET中使用fire-and-forget这样做真的不是一个好主意,有很多关于SO讨论这个问题的问题。