Implement C # asynchronous programming using the learning iterator-async/await (1)

Source: Internet
Author: User

The async/await of. NET 4.5 is really a magic thing. It's so clever that I can't help but wonder about its implementation, but it's hard to get a glimpse of its path. Unexpectedly, I read this article Asynchronous Programming in C # using Iterators, which is like a crash. Meiyu did not dare to exclusive, so I wrote this article to share some of my thoughts with them, and I will give them some valuable insights ...... Strong text "Asynchronous Programming in C # using Iterators" comes from Daniel and has a high vision. Therefore, the description in this article is relatively simple, and the code appended in this article is also relatively obscure, and the monks are blunt and have read and think for dozens of times to give some taste. Therefore, this article will provide a simplified extraction of the original code for further analysis. As mentioned in the strong article, the iterator is used for asynchronous programming in C #. The core idea is to generate a set of IEnumerable <Asyncable> through yield return, and obtain the first Asyncable, execute the Async method and return immediately. The control is handed over to the upper-layer caller. At the same time, the Async method calls back MoveNext to the set before traversing. (The bottom-layer Async method mentioned in this article is implemented by Begin/End, and previously mentioned async/await is just a syntactic sugar.) I have drawn a rough sketch, it took a long time to draw a clear picture. Please forgive me. I hope you can give me some good ideas. Next, we will analyze the code. First, let's take a look at the Main method. The first line is an asynchronous method. The expected result is that the output of the second line is executed before the end of the Asynchronous Method. Copy the code static void Main (string [] args) {AsyncMethod ("http://www.microsoft.com "). execute (); Console. writeLine ("I will execute it first, wait for you"); Console. the AsyncMethod method returns a set of IEnumerable <IAsync>. Note that the returned value of the AsyncMethod method is actually a class object similar to a state machine, this object itself does not Execute internal code statements. We need an Execute method to start traversing the code statements running in this set. The statements in the AsyncMethod method are divided into blocks based on the number of yield return. Each MoveNext method actually executes a piece of code. That is, the number of yield return calls. Copy the code static IEnumerable <IAsync> AsyncMethod (string url) {WebRequest req = HttpWebRequest. create (url); Console. writeLine ("[{0}] starting", url); // asynchronously get the response from http server Async <WebResponse> response = req. getResponseAsync (); yield return response; Console. writeLine ("[{0}] got response", url); Stream resp = response. result. getResponseStream (); foreach (var item in resp. rea DToEndAsync () {yield return item;} Console. WriteLine ("done");} The GetResponseAsync method of the copied code looks very simple and encapsulates Beginxx/Endxxx. Why does it look simple? It will be mentioned later. AsyncPrimitive is the bottom-layer Asyncable object that we will be exposed to. In this article, all Asynchronization is implemented based on it. Public static Async <WebResponse> GetResponseAsync (this WebRequest req) {return new AsyncPrimitive <WebResponse> (req. beginGetResponse, req. endGetResponse);} like the AsyncMethod method, ReadToEndAsync is based on the existing Async method that can return the Async <T> object. Copy the code public static IEnumerable <IAsync> ReadToEndAsync (this Stream stream) {MemoryStream MS = new MemoryStream (); int read =-1; while (read! = 0) {byte [] buffer = new byte [512]; Async <int> count = stream. readAsync (buffer, 0,512); yield return count; Console. writeLine ("[{0}] got data: {1}", "url", count. result); ms. write (buffer, 0, count. result); read = count. result ;}} the code ReadAsync is also asynchronous through Beginxxx/Endxxx. Like GetResponseAsync, It is the Async Method built on the AsyncPrimitive object. Copy the public static Async <int> ReadAsync (this Stream stream, byte [] buffer, int offset, int count) {return new AsyncPrimitive <int> (callback, st) => stream. beginRead (buffer, offset, count, callback, st), stream. endRead);} copy the code below. Let's take a look at the AsyncPrimitive class. You may have found this class and Task <T>. factory. the FromAsync method is somewhat similar. However, if you want to implement it by yourself, you may not be as simple as you think. Copy the public class AsyncPrimitive Code <T>: Async <T> {Action <T> func; public AsyncPrimitive (Func <AsyncCallback, object, IAsyncResult> begin, Func <IAsyncResult, t> end) {this. func = (cont) => begin (delegate (IAsyncResult res) {cont (end (res) ;}, null) ;}public override void ExecuteStep (Action cont) {func (res) =>{ result = res; completed = true; cont ();});}} the copy code is a class consisting of a delegate, an anonymous method, and a lambda expression. Before ExecuteStep is called, it does not do anything, but only builds an Action <T> delegate. The analysis of this category is the main purpose of this article, but the difficulty is that this product can be clearly understood without a few words. After a long time, I translated this category as follows, remove all anonymous methods and lambda expressions. After reading this class, we can see how the iterator achieves Asynchronization. Copy the public class AsyncPrimitive Code <T>: Async <T> {Action <T> func; public AsyncPrimitive (Func <AsyncCallback, object, IAsyncResult> begin, Func <IAsyncResult, t> end) {this. begin = begin; this. end = end; this. func = this. actionActionT;} Func <IAsyncResult, T> End {get; set;} Func <AsyncCallback, object, IAsyncResult> Begin {get; set;} Action <T> RunInCallback {get; set;} Action ActionOute R {get; set;} private void Callback (IAsyncResult ar) {this. runInCallback (this. end (ar);} private void ActionActionT (Action <T> cont) {this. runInCallback = cont; this. begin (this. callback, null);} private void ActionT (T res) {this. result = res; this. completed = true; this. actionOuter ();} public override void ExecuteStep (Action cont) {this. actionOuter = cont; this. func (this. actionT) ;}} copy the code intuitively We can feel how much code lambda has helped us to omit. While being concise, it also increases the difficulty of some understanding. The Code is the best comment. I have no confidence to describe how this class works with words. Finally, add the Execute method. This method actually starts to Execute the Async method. The general idea is to traverse the set, but not through the while LOOP, but through callback to Execute the next MoveNext. Copy the public static void Execute (this IEnumerable <IAsync> async) {AsyncExtensions. run (async. getEnumerator ();} internal static void Run (IEnumerator <IAsync> en) {if (! En. MoveNext () return; en. Current. ExecuteStep () => AsyncExtensions. Run (en);} copy the code and attach it to a running project for debugging trial. The beginning of the original text link is provided, and the original text code is also given for download. Downloading all the recommendations may be more helpful than viewing them. This article is full of confidence at the beginning of writing. I don't know what it will be like when you get bored ...... There should be a second article later, maybe tomorrow, maybe next year ......

Related Article

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.