return to the series "task-based asynchronous mode--Comprehensive introduction" Tasks and Asynchronous Programming model APM (Tasks and the asynchronous programming model) from APM to Tasks
The APM mode relies on two corresponding methods to represent an asynchronous operation: Beginmethodname and Endmethodname. At a high level, the Begin method accepts parameters that are the same as the corresponding synchronization method methodname, and accepts a AsyncCallback and an object state. The Begin method then returns the object state passed to the Begin method returned by Iasyncresult,iasyncresult from its AsyncState property. When the asynchronous operation finishes, the IsCompleted property of IAsyncResult begins to return true, and its AsyncWaitHandle property is set. Furthermore, if the AsyncCallback parameter of the Begin method is non-null, then callback is called and passed to the same IAsyncResult returned from the Begin method. When the asynchronous operation does complete, the operation is connected using the Endmethodname method, retrieving any results or forcing the exception propagation to occur.
Because of the nature of the APM schema structure, it is fairly easy to build an APM wrapper to expose it as a tap implementation. In fact, the. Net Framework 4 provides a help route for conversions in the form of Taskfactory.fromasync.
Public int Read ( byteintint count); .. Public IAsyncResult BeginRead ( byteintint count, Object State ); Public int EndRead (IAsyncResult asyncResult);
Using FROMASYCN, the tap wrapper that implements the method:
public static Task<int > Readasync ( this Stream Stream, byte [] buffer, int offset, int count) { if (stream = = null ) throw new ArgumentNullException ("stream"); return task<int >. Factory.fromasync (stream. BeginRead, Stream. EndRead, buffer, offset, count, null );
This implementation using the FromAsync has the same effect as the following:
Public Statictask<int>Readasync ( ThisStream Stream,byte[] Buffer,intOffsetintcount) { if(Stream = =NULL)Throw NewArgumentNullException ("stream"); varTCS =Newtaskcompletionsource<int>(); Stream. BeginRead (buffer, offset, count, IAR= { Try{TCS. Trysetresult (stream. EndRead (IAR)); } Catch(operationcanceledexception) {TCS. Trysetcanceled (); } Catch(Exception exc) {TCS. Trysetexception (EXC); } }, NULL); returnTCS. Task;}
From tasks to APM
It is also important to be able to take tap implementations and use them where you expect the tap to implement the existing infrastructure where the code is expected to implement APM mode. Fortunately, with the combination of tasks and the fact that the task itself implements IAsyncResult, a simple helper function can be implemented (shown here is a task<tresult> extension, But almost the same function might be used for non-generic tasks):
Public StaticIAsyncResult asapm<t>( ThisTask<t> task, AsyncCallback callback,ObjectState ) { if(Task = =NULL)Throw NewArgumentNullException ("task"); varTCS =NewTaskcompletionsource<t>(state); Task. ContinueWith (t= { if(t.isfaulted) TCS. Trysetexception (t.exception.innerexceptions)Else if(t.iscanceled) TCS. Trysetcanceled (); ElseTCS. Trysetresult (T.result); if(Callback! =NULL) Callback (TCS. Task); }, Taskscheduler.default); returnTCS. Task;}
Now, consider an occasion where tap is implemented:
Public Static task<string> DownloadStringAsync (Uri URL);
And we need to provide APM implementations:
Public IAsyncResult begindownloadstring ( Object State ); Public string Enddownloadstring (IAsyncResult asyncResult);
This can be done using the following code:
Public IAsyncResult begindownloadstring ( Object State ) { return DownloadStringAsync (URL). ASAPM (callback, state);} Public string enddownloadstring (IAsyncResult asyncResult) { return (task<string> ) (AsyncResult). Result;}
Tasks and event-based Asynchronous mode EAP (event-based Asynchronous Pattern)
The event-based Asynchronous Pattern relies on a Methodnameasync method that returns an instance of void, receives and synchronizes the same parameters as the method MethodName method, and instantiates an asynchronous operation. An event handle is registered with an event on the same instance before the instance asynchronous operation, and then triggers these events to provide progress and completion notifications. An event handle is typically a custom delegate type that leverages the type of event arguments derived from ProgressChangedEventArgs or AsyncCompletedEventArgs.
Wrapping an EAP implementation is more complicated because the pattern itself involves more variables and less structure than APM mode. To demonstrate, next wrap a DownloadStringAsync method. DownloadStringAsync accepts a URI parameter that, in order to escalate statistics on multiple progress, triggers the DownloadProgressChanged event when it completes, triggering the Downloadstringcompleted event when completed. The end result is a string containing the content of the page in the specified URI.
Public Statictask<string>downloadstringasync (Uri url) {varTCS =Newtaskcompletionsource<string>(); varWC =NewWebClient (); Wc. Downloadstringcompleted+ = (s,e) = { if(E.error! =NULL) TCS. Trysetexception (E.error); Else if(e.cancelled) TCS. Trysetcanceled (); ElseTCS. Trysetresult (E.result); }; Wc. DownloadStringAsync (URL); returnTCS. Task;}
Tasks and wait handles (Waithandlers) from waithandlers to tasks
Advanced developers may find themselves using the RegisterWaitForSingleObject method of the waithandles and thread pools to asynchronously notify WaitHandle settings, however this is not an asynchronous pattern in nature. We can wrap the RegisterWaitForSingleObject to enable any asynchronous wait-based selection on the WaitHandle:
Public StaticTask Waitoneasync ( ThisWaitHandle WaitHandle) { if(WaitHandle = =NULL)Throw NewArgumentNullException ("WaitHandle"); varTCS =Newtaskcompletionsource<BOOL>(); varRWH =ThreadPool.RegisterWaitForSingleObject (WaitHandle,Delegate{TCS. Trysetresult (true); },NULL, -1,true); vart =TCS. Task; T.continuewith (_= = Rwh. Unregister (NULL)); returnt;}
It is also possible to build an asynchronous semaphore (semaphore) that does not rely on waithandles and works entirely as a task, using the techniques that were previously demonstrated to build on task-based data structures. In fact, the Semaphoreslim type in. Net 4.5 exposes the Waitasync method that opens this. For example, the bufferblock<t> type in the previously mentioned System.Threading.Tasks.Dataflow.dll can be used like this:
Static New Semaphoreslim (n, n); Static Async Task dooperation () { await m_throttle. Waitasync (); // do work M_throttle. Release ();}
From tasks to Waithandlers
As mentioned earlier, the task class implements IAsyncResult, and the implementation of the IAsyncResult exposes a Asycnwaithandle property that returns WaitHandle, which is set when the task is complete. In this way, obtaining a WaitHandle of a task can be implemented as follows:
WaitHandle WH = ((IAsyncResult) Task). AsyncWaitHandle;
Return to the series "task-based asynchronous mode--Comprehensive introduction"
This essay will be over first and look forward to my next series of essays.
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!
with other. NET asynchronous patterns and types interoperate