Is it considered acceptable to not call Dispose() on a TPL Task object? Is it considered acceptable to not call Dispose() on a TPL Task object? multithreading multithreading

Is it considered acceptable to not call Dispose() on a TPL Task object?


There is a discussion about this in the MSDN forums.

Stephen Toub, a member of the Microsoft pfx team has this to say:

Task.Dispose exists due to Taskpotentially wrapping an event handleused when waiting on the task tocomplete, in the event the waitingthread actually has to block (asopposed to spinning or potentiallyexecuting the task it's waiting on).If all you're doing is usingcontinuations, that event handle willnever be allocated
...
it's likely better to rely on finalization to take care of things.

Update (Oct 2012)
Stephen Toub has posted a blog titled Do I need to dispose of Tasks? which gives some more detail, and explains the improvements in .Net 4.5.

In summary: You don't need to dispose of Task objects 99% of the time.

There are two main reasons to dispose an object: to free up unmanaged resources in a timely, deterministic way, and to avoid the cost of running the object's finalizer. Neither of these apply to Task most of the time:

  1. As of .Net 4.5, the only time a Task allocates the internal wait handle (the only unmanaged resource in the Task object) is when you explicitly use the IAsyncResult.AsyncWaitHandle of the Task, and
  2. The Task object itself doesn't have a finalizer; the handle is itself wrapped in an object with a finalizer, so unless it's allocated, there's no finalizer to run.


This is the same kind of issue as with the Thread class. It consumes 5 operating system handles but does not implement IDisposable. Good decision of the original designers, there are of course few reasonable ways to call the Dispose() method. You'd have to call Join() first.

The Task class adds one handle to this, an internal manual reset event. Which is the cheapest operating system resource there is. Of course, its Dispose() method can only release that one event handle, not the 5 handles that Thread consumes. Yeah, don't bother.

Do beware that you ought to be interested in the task's IsFaulted property. It's a fairly ugly topic, you can read more about it in this MSDN Library article. Once you deal with this properly, you should also have a good spot in your code to dispose the tasks.


I'd love to see someone weigh on the technique shown in this post: Typesafe fire-and-forget asynchronous delegate invocation in C#

It looks like a simple extension method will handle all trivial cases of interacting with the tasks and be able to call dispose on it.

public static void FireAndForget<T>(this Action<T> act,T arg1){    var tsk = Task.Factory.StartNew( ()=> act(arg1),                                     TaskCreationOptions.LongRunning);    tsk.ContinueWith(cnt => cnt.Dispose());}