Implementing the task-based Asynchronous Pattern

Source: Internet
Author: User
Tags net thread

Return to the series "task-based asynchronous mode--Comprehensive introduction"Build Method Compiler Generation

In the. NET Framework 4.5, the C # compiler implements Tap. Any method marked with the Async keyword is an async method, and the compiler uses tap to perform the necessary transformations to implement the method asynchronously. Such a method should return a task or task<tresult> type. In the latter case, the method body should return a TResult, and the compiler will ensure that the returned task<tresult> is available. Similarly, unhandled exceptions in the method body are marshaled to the output task, causing the returned task to end in faulted state. One exception is if operationcanceledexception (or derived type) is unhandled, the returned task ends in the canceled state.

manually generated

Developers can implement taps manually, just like compilers or better control the implementation of methods. The compiler relies on exposed surface areas from the System.Threading.Tasks namespace (and types supported in the System.Runtime.CompilerServices built on System.Threading.Tasks), as well as directly available to developers The function. When the TAP method is implemented manually, the developer must ensure that the returned task is completed when the asynchronous operation completes.

Hybrid Builds

Mixing the implementation of core logic in compiler-generated implementations is often useful for manually implementing taps. For example, in order to avoid an exception that is exposed by the method's direct caller rather than by a task, such as:

 Publictask<int> MethodAsync (stringinput) {    if(Input = =NULL)Throw NewArgumentNullException ("input"); returnmethodasyncinternal (input);}Private Asynctask<int> methodasyncinternal (stringinput) {...//code that uses await}

Parameters should be changed outside of the compiler-generated async method, and another case where the delegate is useful is when a "fast channel" optimization can be implemented by returning a cached task.

Work Load

Compute constrained and I/O constrained asynchronous operations can be implemented by the TAP method. However, when the implementation of tap is exposed from a library, it should be provided only to workloads that contain I/O operations (they can also contain calculations, but should not contain only calculations). If a method is purely computational, it should be exposed only through an asynchronous implementation, and the consumer can then choose whether to wrap the call of that synchronous method into a task and/or to implement parallelism in order to offload the task to other threads.

Calculation Limits

The task class is best suited to represent computationally intensive operations. By default, in order to provide a valid execution operation, it takes advantage of. NET thread pool, but also provides a lot of control over when, where, and how asynchronous computations are performed.

There are several ways to generate compute-constrained tasks.

    1. in. Net 4, the primary method for starting a new compute-constrained task is taskfactory.startnew (), which takes a delegate that executes asynchronously (typically an action or a func<tresult >). If an action is provided, the returned task represents the asynchronous execution of that delegate. If a func<tresult> is provided, a task<tresult> is returned. There is an overload of StartNew (), which accepts Cancellationtoken,taskcreationoptions, and TaskScheduler, which provide fine-grained control over the dispatch and execution of the task. The factory instance acting on the current dispatcher can act as a static property of the task class, such as Task.Factory.StartNew ().
    2. in. Net 4.5, the task type exposes a static Run method as a shortcut to a StartNew method that can be easily used to start a compute-constrained task on a thread pool. Starting with. Net 4.5, this is a more popular mechanism for starting a compute-constrained task. The startnew is used directly when the behavior requires more granular control. The
    3. task type exposes constructors and the Start method. If you must have a detached self-dispatching constructor, these are available (as previously mentioned, the exposed APIs must return only the tasks that have been started). The
    4. task type exposes multiple overloads of ContinueWith. When another task is completed, the method creates a new task that will be dispatched. This overload accepts Cancellationtoken,taskcreationoptions, and TaskScheduler, which provide fine-grained control over the scheduling and execution of tasks. The
    5. TaskFactory class provides Continuewhenall and Continuewhenany methods. These methods create a new task that is about to be dispatched when all or any one of the supplied series of tasks is completed. With ContinueWith, there is support for scheduling control and task execution.

Consider the following asynchronous method of rendering a picture. The task body can obtain cancellation tokens so that when a rendering occurs, the code may exit prematurely if a revocation request arrives. Furthermore, if a revocation request occurs before the rendering begins, we can also block any rendering.

 PublicTask<bitmap>Renderasync (ImageData data, CancellationToken cancellationtoken) {returnTask.run (() =    {        varBMP =NewBitmap (data. Width, data.        Height);  for(inty=0; Y<data. Height; y++) {cancellationtoken.throwifcancellationrequested ();  for(intx=0; X<data. Width; X + +) {...//render pixel [x, y] into BMP            }        }        returnbmp; }, CancellationToken);}

If at least one of the following conditions is correct, the compute-constrained tasks will end with a canceled state:

    1. Before a task is over to the taskstatus.running state, CancellationToken provides a parameter (such as Startnew,run) for a method of creating a revocation request.
    2. There is such a task that has an unhandled operationcanceledexception inside it. The operationcanceledexception contains cancellationtoken passed to the task with the same name as the CancellationToken property, and the CancellationToken has issued a revocation request.

If there is another unhandled exception in the task body, the task ends in the state of faulted, and any attempt to wait on the task or the result of accessing it will result in an exception being thrown.

I/O limitations

Tasks created with the taskcompletionsource<tresult> type should not be returned directly by all executing threads. Taskcompletionsource<tresult> exposes a task property that returns a related task<tresult> instance. The life cycle of the task is controlled by the methods exposed by the taskcompletionsource<tresult> instance, in other words, these examples include Setresult, setexception, setcanceled, and their tryset* variables.

Consider the need to create a task that will be completed after a specific time. For example, this might be useful when a developer wants to delay an activity for a period of time in a UI scenario. The System.Threading.Timer class in net already provides this ability to invoke a delegate asynchronously after a specific time, and we can use taskcompletionsource<tresult> Put a task on the timer, for example:

 Public Static Task<datetimeoffset> Delay (int  millisecondstimeout) {    varNew Taskcompletionsource<datetimeoffset>();     New Timer (self =    {(        IDisposable) self). Dispose ();        Tcs. Trysetresult (Datetimeoffset.utcnow);     -1);     return TCS. Task;}

In. Net 4.5, Task.delay () was born for this purpose. For example, such a method can be used inside another async method to implement an asynchronous rotation loop:

 Public Static AsyncTask Poll (Uri URL, cancellationtoken cancellationtoken, IProgress<BOOL>progress) {     while(true)    {        awaitTask.delay (Timespan.fromseconds (Ten), CancellationToken); BOOLSuccess =false; Try        {            awaitdownloadstringasync (URL); Success=true; }        Catch{/*Ignore Errors*/} progress.    Report (success); }}

The

does not have a non-generic copy of taskcompletionsource<tresult>. However,,task<tresult> derives from Task, so the generic taskcompletionsource<tresult> can be used for those I/O-constrained methods, They all take advantage of a fake TResult source (Boolean is the default choice, and if the developer cares about the task<tresult> consumer of task down, then a private TResult type can be used to simply return a task.) For example, the previous delay method was developed to return the current time along the resulting task<datetimeoffset>. If such a result value is unnecessary, then the method can be replaced by the following code (notice the change of the return type and the change of the Trysetresult parameter):

 Public Static Task Delay (int  millisecondstimeout) {    varnew taskcompletionsource<  BOOL>();     New Timer (self =    {(        IDisposable) self). Dispose ();        Tcs. Trysetresult (true);     -1);     return TCS. Task;}
tasks for mixing compute limits and I/O limits

Asynchronous methods are not limited to computation-constrained or I/O-constrained operations, but can represent a mixture of both. In fact, it is often the case that multiple asynchronous operations of different natures are grouped together to produce larger mixed operations. For example, before thinking about the Renderasync method, the method performs a computationally intensive operation based on some input imagedata to render an image. The ImageData may come from a Web service that we have asynchronous access to:

 Public Async Task<bitmap> downloaddataandrenderimageasync (    cancellationtoken cancellationtoken) {      varawait  downloadimagedataasync (cancellationtoken);     return await Renderasync (ImageData, CancellationToken);}

This example also shows how a single cancellationtoken is threaded through multiple asynchronous operations.

Return to the series "task-based asynchronous mode--Comprehensive introduction"

TKB to Jane: http://www.cnblogs.com/farb/

qq:782762625

Welcome to communicate with you!

This article copyright belongs to the author and the blog Garden altogether, welcome reprint. Without the consent of the author, the original link and the author must be clearly marked on the article page, otherwise the right to pursue legal liability is reserved.
If you think this article is good or something, you can click on the "recommended" button in the lower right corner, because your support is my biggest motivation to continue writing and sharing!

Implementing the task-based Asynchronous Pattern

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.