5

I'm using similar code to below for a non critical fire-and-forget operation in ASP.NET

private void SomeMethod()
{
    FireAndForgetAsync();
}

private async Task FireAndForgetAsync()
{
    // Simulate medium running IO blocking operation
    await Task.Delay(sleepTime).ConfigureAwait(false);

    // Simulating the rare scenario where an error occurs
    throw new Exception("An Error Occurred");
}

The exception is captured in the task being returned from the async method, which prevents an unhandled exception altogether crashing the application..

But would this code cause any memory leaks? Because the returned Task (and its exception) are not assigned / accessed? My thoughts are that it would simply be garbage collected unless some .NET framework code is holding a reference to the task..

cwills
  • 2,136
  • 23
  • 17
  • 5
    You should be using [`QueueBackgroundWorkItem`](http://blogs.msdn.com/b/webdev/archive/2014/06/04/queuebackgroundworkitem-to-reliably-schedule-and-run-long-background-process-in-asp-net.aspx) for this. If you're limited to .NET 4.5.1 or earlier, you can use `IRegisteredObject`, check Stephen Cleary's ["Fire and Forget on ASP.NET"](http://blog.stephencleary.com/2014/06/fire-and-forget-on-asp-net.html). – noseratio Jun 22 '14 at 00:59
  • 2
    There won't be any problem with the `Task`. You will find some explanation why you don't need to dispose the `Task` here: http://blogs.msdn.com/b/pfxteam/archive/2012/03/25/10287435.aspx – PiotrWolkowski Jun 22 '14 at 01:35
  • Note, that background work is never guaranteed to complete in ASP.NET in case the worker process recycles without warning. Expect to sometimes lose such work without any indication. – usr Jun 22 '14 at 09:06

2 Answers2

5

There isn't a risk for a memory leak in your code. At least From the snippet you provided.

Though, your application may be terminated by the CLR when the Task is being finalized due to an unhandled Exception.

If you create a Task, and you don't ever call task.Wait() or try to retrieve the result of a Task, when the task is collected by the garbage collector, it will tear down your application during finalization. For details, see MSDN's page on Exception Handling in the TPL.

(Reed Copsey's Answer)

There are more than one solution/workarounds for this. You can find more information about this in this SOF post: A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was

(As I3arnon mentioned, this behavior is changed in .Net 4.5. )

Community
  • 1
  • 1
m1o2
  • 1,549
  • 2
  • 17
  • 27
  • 4
    That behavior was changed in .net 4.5: [Task Exception Handling in .NET 4.5](http://blogs.msdn.com/b/pfxteam/archive/2011/09/28/task-exception-handling-in-net-4-5.aspx) – i3arnon Jun 22 '14 at 09:08
  • "To make it easier for developers to write asynchronous code based on Tasks, .NET 4.5 changes the default exception behavior for unobserved exceptions. While unobserved exceptions will still cause the UnobservedTaskException event to be raised (not doing so would be a breaking change), the process will not crash by default" – i3arnon Jun 22 '14 at 09:09
  • 1
    @I3arnon Thanks, I didn't knew that! :) – m1o2 Jun 22 '14 at 09:17
  • 1
    I also learned that from an SO comment: http://stackoverflow.com/a/20025703/885318 – i3arnon Jun 22 '14 at 09:19
2

There's no danger of a memory leak in your code. As long as the task has ended (which it has) there's nothing stopping the Garbage Collector of collecting it. You may use a lot of memory if you fire a unusual amount of those tasks, but they will be GCed.

There would be a chance for memory leaks if those tasks will not end (if they have a while (true) for example) or if you were keeping references to them.


As mentioned in the comments. Using "fire and forget" and async-await is heavily discouraged.

i3arnon
  • 113,022
  • 33
  • 324
  • 344