Async CTP opens up a avenue for us to implement asynchronous operations in a single thread, especially for WCF in SL, which frees us from tedious event processing, originally, I wanted to write a series of notes on RPC framework implemented by socket in SL (used in my project, however, some people mentioned that async CTP should be used to circumvent the complicated problem caused by the Asynchronous Method of WCF, in fact, async CTP is not flexible enough in my project (it should be that WCF is not flexible enough for my application), but let's put down that series first to see what async CTP can do.
This article will not introduce how to use async CTP, but will only analyze how the compiler works accordingAsyncAndAwaitThe two keywordsCodeMake correct changes to achieve single-thread asynchronous operations.
For more information about single-thread Asynchronization, see programming user interfaces using F # workflows
To understand async CTP, we strongly recommend this article asynchronous programming in C # using iterators
Let's take a look at several important classes in asyncctplibrary_silverlight.dll. runtime. in the compilerservices namespace, find these classes asyncmehodbuilder, asyncmethodbuilder <tresult>, voidasyncmethodbuilder, taskawaiter, taskawaiter <tresult>, and system. threading. the task and task <tresult> under tasks can be identified by their names. Here is a brief introduction:
Asyncmethodbuilder: IfAsyncBefore being applied to a task object, the compiler uses this class.
Asyncmethodbuilder <tresult>: IfAsyncBefore being applied to a task <tresult>, the compiler uses this class.
Voidasyncmethodbuilder:AsyncBefore being applied to a method declaration, the compiler uses this class. (Therefore, The async keyword can be added only when the return value is void)
Taskawaiter: corresponds toAwaitKeyword.
Taskawaiter <tresult>: corresponds toAwaitKeyword.
Task and task <tresult>: corresponds to two await instances.
To achieveAsync,AwaitThe compiler willAsyncThe method marked with the keyword is compiled into an embedded class of the class where the method is located. All variables that appear in the method body are declared as fields of the class. If it is an instance method, the object represented by this is also declared as a field. This class has two core members: an int to save the code execution to that step, which is called step for the time being, and a method to execute the real action, which is called nextstep for the time being, the entire logic looks like this:
1:Public VoidNextstep ()
2:{
3:Switch(STEP)
4:{
5:Case1:
6:...
7:Step ++;
8:Break;
9:Case2:
10:...
11:Step ++;
12:Break;
13:Case3:
14:....
15:Step ++;
16:Break;
17:.
18:.
19:.
20:}
21:}
Does it look like yield return?
InAsyncThe markup method is generally like this. Assume that the method is compiled into a class named asyncmethodclass:
1:Asyncmethodclass A =NewAsyncmethodclass ();
2:A. xxx = xxx;
3:A. YYY = YYY;
4:.
5:.
6:.
7:A. nextstep ();
So what is the basis for compilation to determine how many blocks A method can be divided? In fact, the compilerAsyncTheAwaitKeyword for distribution, if there isAwaitSo there should be two steps, if there are twoAwaitThere should be three steps. Each step should be inAwait(Except for the first step), andAwait(Except for the last step ). I can see why.AsyncIt can only be marked on a function without a return value, because the nextstep function must be an action type without a return value and be passed to the beginwait method of await. Therefore, in the above Code, there is no way to use the theory in the last 7th rows:
1:ReturnA. nextstep ();
After figuring out what the compiler is doing, let's look at an example from the async CTP samples fragment:
1:PublicAsyncVoidAsyncintroserial ()
2:{
3:VaR client =NewWebClient ();
4:
5:Writelinepagetitle (await client. downloadstringtaskasync (NewUri (Http://www.weather.gov")));
6:Writelinepagetitle (await client. downloadstringtaskasync (NewUri (Http://www.weather.gov/climate")));
7:Writelinepagetitle (await client. downloadstringtaskasync (NewUri (Http://www.weather.gov/rss")));
8:}
After the above theory, the async and await keywords are not used, and the rewrite is as follows:
1:Taskawaiter <String> Wait1;
2:Taskawaiter <String> Wait2;
3:Taskawaiter <String> Wait3;
4:IntStep = 0;
5:WebClient WC =NewWebClient ();
6:Private VoidAsyncmethodwithoutkeywords ()
7:{
8:Switch(STEP)
9:{
10:Case0:
11:Task <String> T1 = WC. downloadstringtaskasync (NewUri (Http://www.weather.gov"));
12:Step ++;
13:Wait1 = t1.getawaiter <String> ();
14:Wait1.beginawait (NewAction (asyncmethodwithoutkeywords ));
15:Break;
16:Case1:
17:Writelinepagetitle (wait1.endawait ());
18:Task <String> T2 = WC. downloadstringtaskasync (NewUri (Http://www.weather.gov/climate"));
19:Step ++;
20:Wait2 = t2.getawaiter <String> ();
21:Wait2.beginawait (NewAction (asyncmethodwithoutkeywords ));
22:Break;
23:Case2:
24:Writelinepagetitle (wait2.endawait ());
25:Task <String> T3 = WC. downloadstringtaskasync (NewUri (Http://www.weather.gov/rss"));
26:Step ++;
27:Wait3 = t3.getawaiter <String> ();
28:Wait3.beginawait (NewAction (asyncmethodwithoutkeywords ));
29:Break;
30:Case4:
31:Writelinepagetitle (wait3.endawait ());
32:Break;
33:}
34:}
We can find that the execution result is the same as that of async and await.
The core of async CTP is actually the task design. The CTP library implements async to task for WebClient and WCF. You need to define the task yourself for some custom methods in the project, however, you can define tasks using your own methods and use the methods described in this article for packaging (especially when you used emit or the dynamic keyword for AOP ), you can discard the aysnc and await keywords to prevent the compiler from modifying the code. The advantage is that breakpoint debugging can be performed normally.