Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Task.Run vs. ContinueWith in ASP.NET MVC

In my ASP.NET MVC 4 application, say I have some async method:

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

Now, one can call this method like this:

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

or this:

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

Note that in both versions the caller doesn't wait for the background task to finish. It's just fire and forget.

While both versions work identical (ignore exception handling here) on regular .NET apps, on a MVC app, when calling the code from a MVC controller method, Debug.WriteLine is only executed in the Task.Run version - but not in the ContinueWith version.

Can anyone shed some light onto why these two versions are working differently when called in a MVC controller method?

like image 350
Sebastian Krysmanski Avatar asked Apr 15 '14 09:04

Sebastian Krysmanski


1 Answers

This is probably something specific to your web app, so I can only speculate, but here's what I think:

  • It should work if you do this:

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

    This would be more close to the Task.Run version, where the continuation runs synchronously.

  • Right before you call DoSomeBackgroundWork directly from the controller method, add this:

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

    If the output is anything but ThreadPoolTaskScheduler, I might be able to further explain this behavior (as I've just dealt with a somewhat related problem here).

BTW, using fire-and-forget in ASP.NET like this is really not a good idea, there's a lot of questions on SO discussing this.

like image 83
noseratio Avatar answered Sep 27 '22 17:09

noseratio