Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do I need to dispose of a Task?

I am having fun working with System.Threading.Tasks. Many of the code samples I see, however, look something like so:

Dim lcTask = Task.Factory.StartNew(Sub() DoSomeWork())
Dim lcTaskLong = Task.Factory.StartNew(Sub() DoSomeWork(), TaskCreationOptions.LongRunning)
Task.WaitAll(lcTask, lcTaskLong)

That's the extent of the sample.
Tasks implement IDisposable, so obviously I'm supposed to dispose of them, but what if I just want to "Fire and Forget"?

If I don't dispose, will I leak threads/handles/memory/karma? Am I using tasks "wrong"? (Should just use a delegate and leave tasks alone?)

Can I dispose in a ContinueWith()? (That seems like playing Russian Roulette.)

like image 430
Kevin Buchan Avatar asked May 13 '11 00:05

Kevin Buchan


People also ask

Do I need to call dispose when disposing of tasks?

However, particularly if your app targets the .NET Framework 4.5 or later, there is no need to call Dispose unless performance or scalability testing indicates that, based on your usage patterns, your app's performance would be improved by disposing of tasks.

What does dispose () method do in Java?

Disposes the Task, releasing all of its unmanaged resources. A Boolean value that indicates whether this method is being called due to a call to Dispose (). The task is not in one of the final states: RanToCompletion, Faulted, or Canceled.

What does “disposal” mean?

Now, when looking up the term dispose of, there is a good chance that you will also stumble across the term “disposal” too. The meaning of disposal is actually rather similar to that of dispose of. This is because they both mean to get rid of or to discard.

What is the difference between dispose () and dispose (Boolean)?

Dispose () Releases all resources used by the current instance of the Task class. Dispose (Boolean) Disposes the Task, releasing all of its unmanaged resources.


1 Answers

While the normal rule of thumb is to always call Dispose() on all IDisposable implementations, Task and Task<T> are often one case where it's better to let the finalizer take care of this.

The reason Task implements IDisposable is mainly due to an internal WaitHandle. This is required to allow task continuations to work properly, and only used when there is a continuation on a Task. If there is no continuation, the Task's Dispose method has no real effect - so in this case, it's not required.

That being said, in most cases where there is a Task continuation, it's often very, very difficult to write your code in a way that allows you to properly call Dispose(). Using statements typically do not work with Task instances, since the Task call is typically asynchronous in nature. It's very easy to dispose of the Task far too early, especially when using the using statement.

If, in your case, it's relatively simple to keep a reference to the Task and call Dispose() on it correctly, I would do so. However, if this is going to cause your logic to get much more complex, I would typically pretend that Task isn't IDisposable, and allow it to be cleaned up in the finalizer for the Task.

For more details, I'd recommend reading this thread on the MSDN forums where Stephen Toub describes why Task implements IDisposable in detail, and provides similar guidance to my suggestion above.

like image 93
Reed Copsey Avatar answered Sep 19 '22 19:09

Reed Copsey