Fire and forget async method in asp.net mvc Fire and forget async method in asp.net mvc asp.net asp.net

Fire and forget async method in asp.net mvc


First off, let me point out that "fire and forget" is almost always a mistake in ASP.NET applications. "Fire and forget" is only an acceptable approach if you don't care whether DeleteFooAsync actually completes.

If you're willing to accept that limitation, I have some code on my blog that will register tasks with the ASP.NET runtime, and it accepts both synchronous and asynchronous work.

You can write a one-time wrapper method for logging exceptions as such:

private async Task LogExceptionsAsync(Func<Task> code){  try  {    await code();  }  catch(Exception exception)  {    m_log.Error("Call failed: " + exception.ToString());  }}

And then use the BackgroundTaskManager from my blog as such:

BackgroundTaskManager.Run(() => LogExceptionsAsync(() => DeleteFooAsync()));

Alternatively, you can keep TaskScheduler.UnobservedTaskException and just call it like this:

BackgroundTaskManager.Run(() => DeleteFooAsync());


As of .NET 4.5.2, you can do the following

HostingEnvironment.QueueBackgroundWorkItem(async cancellationToken => await LongMethodAsync());

But it only works within ASP.NET domain

The HostingEnvironment.QueueBackgroundWorkItem method lets you schedule small background work items. ASP.NET tracks these items and prevents IIS from abruptly terminating the worker process until all background work items have completed. This method can't be called outside an ASP.NET managed app domain.

More here: https://msdn.microsoft.com/en-us/library/ms171868(v=vs.110).aspx#v452


The best way to handle it is use the ContinueWith method and pass in the OnlyOnFaulted option.

private void button1_Click(object sender, EventArgs e){    var deleteFooTask = DeleteFooAsync();    deleteFooTask.ContinueWith(ErrorHandeler, TaskContinuationOptions.OnlyOnFaulted);}private void ErrorHandeler(Task obj){    MessageBox.Show(String.Format("Exception happened in the background of DeleteFooAsync.\n{0}", obj.Exception));}public async Task DeleteFooAsync(){    await Task.Delay(5000);    throw new Exception("Oops");}

Where I put my message box you would put your logger.