(translated). NET4. x parallel Tasks task need to be freed?

Source: Internet
Author: User

Summary: This blog post explains why you should not call Dispose () after a task in. NET 4.X has finished using it. and description. NET4.5 part of the improvements to the. NET4.0 Task object: Mitigating the task's dependency on the WaitHandle object, and enhancing the accessibility of the task to its members after releasing it.

I have received this question many times:

"The task implements the IDisposable interface and exposes the Dispose () method, does that mean we are going to release all the tasks?" ”

Overview

    1. Here is my brief answer to the question:

"No, don't release the task you hold." ”

    1. Here is my medium answer to the question:

"No, don't release the task you hold, unless the performance report or scalability test report shows that you need to release the task to meet your performance goals." If you find a task that needs to be freed, you must 100% make sure that the task is completed at your release point and is not being used elsewhere. ”

    1. Below, you can find a casual reading time, which is my long answer to the question:

Why call the task's Dispose ()?

As stated in the. NET Framework Design Guide, a type should implement the IDisposable interface itself if it holds other resources that implement the IDisposable interface. Within a task, a WaitHandle object may be assigned to wait for the task to complete. The WaitHandle implements the IDisposable interface because it holds the Safewaithandle kernel wait handle, so the task implements the IDisposable interface. If you do not voluntarily release the Safewaithandle handle, the final finalizer will also clean it up, but it cannot immediately clean up the resource and leave the cleanup workload to the system. By implementing the IDisposable interface to a task, we can enable developers to release resources proactively and in a timely manner.

Problem

If you assign a WaitHandle to each task, releasing the task will be a good measure because it can improve performance. But this is not the case, in reality, the situation of assigning WaitHandle to tasks is very rare. In. NET 4.0, WaitHandle delays initialization in the following situations: Access ((IAsyncResult) Task). The AsyncWaitHandle member, or the WaitAll ()/waitany () method that invokes the task (both methods are in the. In the NET4.0 version, the internal is implemented as a task-based WaitHandle object). This makes it more difficult to answer the question "Should I release a task" because if the task uses WaitAll ()/waitany (), releasing the task is a good choice.

 Public Interface iasyncresult{    objectget;}     Get ; }     BOOL Get ; }     BOOL Get ; }}


In. NET 4.0, when a task is freed, most of its member accesses will throw a objectdisposedexceptions exception. This makes it difficult for the completed task to be safely cached because after one consumer releases the task, another consumer cannot access some of the important members of the task, such as the ContinueWith () method or the result property.

Here's another problem: The task is the underlying synchronization primitive. If a task is used for parallelization, as in a fork/join mode ("branching/merging" mode) it is easy to know when to complete them and when no one will use them again, such as:

var New task[3]; tasks[0] = compute1async (); tasks[1] = compute2async (); tasks[2] =foreach(var in Tasks) task. Dispose ();


However, when using task continuations, it is difficult to tell when it will be completed and when no one is using them, such as:

Compute1async (). ContinueWith (T1 = {     t1. Dispose ();     ...});


The example succeeds in releasing the task returned by Compute1async (), but it ignores how to release the task returned by ContinueWith (). Of course, we can use the same method to release this task.

Compute1async (). ContinueWith (T1 = {     t1. Dispose ();      = = T2. Dispose ());


But we cannot release the task returned by the second ContinueWith (). Even using the new async/await async method in c#5.0 does not resolve. For example:

string await  stringawaitstringawait compute3async (S2);


If you want to release these tasks, I need to make a rewrite like this:

string NULL NULL NULL  using(var t1 = compute1async ())     awaitusing (var t2 = Compute2async (S1))      await  using(var t3 = compute3async (s2))     await T3;

Solution Solutions

Because releasing most of the tasks like above is tedious, so in. Some improvements have been made to the task's Dispose () in NET4.5:

    1. We make it less possible for you to create WaitHandle objects for a task. In. NET4.5 we have rewritten the task's WaitAll () and WaitAny () so that the two methods are no longer dependent on the WaitHandle object (so WaitAll (), WaitAny (), wait () are based on spin waits), Avoid using WaitHandle objects in the internal implementation of a task, and provide async/await-related asynchronous functionality. Therefore, only when you display the IAsyncResult.AsyncWaitHandle member that accesses a task assigns a WaitHandle object to a task, this requirement is rare. This means that in addition to this very rare situation, releasing a task is not required.
    2. We make the task available after release. You can use all public members of a task even if the task has already been disposed, and the performance of accessing those members is the same as before releasing the task. Only IAsyncResult.AsyncWaitHandle members you cannot use, because this is the object that you really release when you release a task, and you will still throw objectdisposedexception when you try to access this property after releasing the task. Further, it is now recommended to use the Async/await async method and the task-based asynchronous programming pattern to reduce the use of IAsyncResult, even if you continue to use ((IAsyncResult) Task), It is also very rare to call its AsyncWaitHandle members.
    3. The Task.dispose () method does not even exist in the assembly referenced by the. NET Metro Style Application framework (that is, the task in this framework does not implement the IDisposable interface).

Guide

So, again, we return to the brief answer: "No, don't release your task." "It is often difficult to find a suitable release point, and there is almost no reason to take the initiative to release the task (because of the call (IAsyncResult) Task). The requirements of the AsyncWaitHandle members are very rare, and you cannot even invoke the Dispose () method of the task in the assembly referenced by the. NET Metro style application framework.

More Resource Sources Blog: FAQs on async and await

(translated). NET4. x parallel Tasks task need to be freed?

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.