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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With