Based on the asynchronous programming of TPL, the simplest is to use a Task object, and the simplest way to create a task object is to use the LAMDA expression:
static void Main (string[] args) {//Create the cancellation token source Cancellationtok
Ensource Tokensource = new CancellationTokenSource ();
Create the cancellation token CancellationToken token = Tokensource.token;
int i = 0;
int value = 10; Create the "the" which we let run fully task Task1 = new Task (() => {for (i) = 0; i < Int32.MaxValue;
i++) {value++; BOOL cancelled = token.
WaitHandle.WaitOne (10000);
if (cancelled) {throw new operationcanceledexception (token);
}}, token); Start Task Task1.
Start ();
Cancel the token tokensource.cancel (); Wait for input before exiting Console.WriteLine ("Main Method compleTe. Press ENTER to finish with value = "+ value."
ToString ());
Console.ReadLine (); }
Well, inside the LAMDA expression of the Task object, we refer to the external member: I, value, token. So in the end. What the net compiler did to enable us to access these external members. The principle is very simple, this is after Ilspy decompile the source code (the Special decompile option all disable off):
listing_13.listing_13
private static void Main (string[] args)
{
Listing_13.<>c__displayclass1 <>c__displayclass = new Listing_13.<>c__displayclass1 ();
CancellationTokenSource CancellationTokenSource = new CancellationTokenSource ();
<>c__displayclass.token = Cancellationtokensource.token;
<>c__displayclass.i = 0;
<>c__displayclass.value = ten;
Task task = new Task (new Action (<>C__DISPLAYCLASS.<MAIN>B__0), <>c__displayclass.token);
Task. Start ();
Cancellationtokensource.cancel ();
Console.WriteLine ("Main method complete.") Press ENTER to finish with value = "+ <>c__displayclass.value.tostring ());
Console.ReadLine ();
}
. NET compiler, creating a new class for the LAMDA expression, <>c__dislayclass (this is very strange, I remember await compiled it to generate a structure, is that. Net 4.5 has been optimized. , and the LAMDA expression itself becomes a function <main>b_0, and the referenced external member is changed to a class member. I,. Value,. token, note that there are no extra variables to produce. Notice that in the entire main function, here all the variables referenced by Lamda
Well, let's see what this <>c__displayclass is:
[Compilergenerated]
Private Sealed class <>c__displayclass1
{public
CancellationToken token;
public int i;
public int value;
public void <main>b__0 ()
{
this.i = 0;
while (This.i < 2147483647)
{
this.value++;
BOOL flag = This.token.WaitHandle.WaitOne (10000);
if (flag)
{
throw new operationcanceledexception (This.token);
}
this.i++
}}
}
The attribute compilergenerated indicates that this is generated by the compiler, so the class name can use the <> prefix. This class is nothing special, just like the LAMDA expression. So, now everything is clear. Haha, as Houtie said, the source code before, no secrets.
Note that the compiler transforms the external variable into a member of the Displayclass, so if the asynchronous method has not been executed before (or before the execution is done), the value of the external variable is changed, and the asynchronous method is affected. (equivalent to modifying the value of a member variable)