. NET (C #): await returns the async method of the Task,

Source: Internet
Author: User

. NET (C #): await returns the async method of the Task,

I.Thread world before FrameWork 4.0  

Before. NET FrameWork 4.0, if we use a thread. There are generally the following methods:

  • Use the System. Threading. Thread class, call the instance method Start () to Start a new Thread, and call the Abort () method to terminate the Thread in advance.
  • Use the System. Threading. ThreadPool class to call the static method QueueUserWorkItem (), put the method into the thread pool queue, and the thread pool to control the call.
  • Use a series of asynchronous methods such as BeginInvoke, EndInvoke, BeginRead, EnRead, BeginWrite, and EndWrite.
  • Use the System. ComponentModel. BackgroundWorker control to call the instance method RunWorkerAsync () and start a new thread.

II.Overview of. Net traditional asynchronous programming 

  • Asynchronous programming model (APM), in which asynchronous operations are represented by a pair of in/End methods (such as FileStream. BeginRead and Stream. EndRead.
  • Event-based asynchronous mode (EAP) in which asynchronous operations are performed by methods/event pairs named "Operation name Async" and "Operation name Completed" (such as WebClient. downloadStringAsync and WebClient. downloadStringCompleted. (EAP is introduced in. NET Framework 2.0 and is often used in silverlight or wpf ).

III.Advantages and functions of tasks

  • After a task is started, you can register the callback as a task continuation at any time.
  • Use the ContinueWhenAll and ContinueWhenAny methods, WaitAll methods, or WaitAny methods to coordinate multiple operations to respond to the Begin _ method.
  • Encapsulate asynchronous I/O binding and computing Binding operations in the same Task object.
  • Monitors the status of the Task object.
  • Use TaskCompletionSource to mail the operation status to the Task object.

 

As we all know, the async method can only return void, Task, and Task <T>.

 

For the async method that returns void, it is not awaitable, so other methods cannot call it using the await method, but the async method that returns the Task can.

 

So when the async method returns a Task and await goes on, What is the concept of a Task that is await? Is the first Task in the async method await? No, it indicates the full execution of the target async method, including the connected tasks separated by await, but not the multi-thread execution caused by non-await.

 

The following code: In doo, it is an async method that returns the Task, and await calls doo in the test method, and then calls test in the Main method (because the Main method does not allow async, so we need to add another async method to use await)

Static void Main (string [] args)

{

Test ();

Log ("Main: After test is called ");

Thread. Sleep (Timeout. Infinite );

}

 

// Async is not allowed for the Main method, so we use await in this method.

Static async void test ()

{

Log ("test: Before await ");

Await doo ();

Log ("test: After await ");

}

 

// Return The async method of the Task

Static async Task doo ()

{

Log ("doo: Task Result:" + await Task. run () => {Thread. sleep (1000); log ("Task"); return 1 ;}));

Log ("doo: Task Result:" + await Task. run () => {Thread. sleep (1000); log ("Task"); return 2 ;}));

Log ("doo: Task Result:" + await Task. run () => {Thread. sleep (1000); log ("Task"); return 3 ;}));

Thread. Sleep (1000 );

Console. WriteLine ("the Thread. Sleep in doo is executed out of Task ");

}

 

// Output method: display the ManagedThreadId of the current thread

Static void log (string msg)

{

Console. WriteLine ("{0 }:{ 1}", Thread. CurrentThread. ManagedThreadId, msg );

}

 

The above code will output:

1: test: Before await

1: Main: After test is called

3: Task

3: doo: Task result: 1

4: Task

4: doo: Task result: 2

3: Task

3: doo: Task result: 3

Thread. Sleep out of Task in doo is finished.

3: test: After await

 

The first two sentences are simple. Call the test method. The content after await will be added to the end of the target Task, and test will return immediately, so the output "Main: after the test is called" is displayed ", at the same time, they are all executed in the main thread, so ManagedThreadId is 1.

 

The next step is the execution of another Task (of course, in another thread, it is also the target Task of await in the test method ). This so-called Task is the full execution of the doo method. Therefore, tasks executed in three sequence in doo (connected one by one through await) are executed in sequence. Therefore, the Task outputs results 1, 2, and 3. The ManagedThreadId of the first Task is 3, the second is 4, and the third is 3, because the internal execution of the Task uses the CLR thread pool, so the thread is reused.

 

The doo method is not complete yet. The code behind the doo method is executed after the last await Task is executed. Therefore, the Thread outside the Task in doo is output. sleep execution is complete.

 

Finally, after doo executes test await completely, the result is output in the last line: test: await.

 

 

As I said above: the tasks returned by the await async method represent "All execution of the target async method, including connection tasks separated by await, but not multi-thread execution caused by non-await ".

Therefore, if you change the async method of the returned Task (that is, the doo method in the previous example) to the following:

// Return The async method of the Task

Static async Task doo ()

{

Log ("doo: Task Result:" + await Task. run () => {Thread. sleep (1000); log ("Task"); return 1 ;}));

Log ("doo: Task Result:" + await Task. run () => {Thread. sleep (1000); log ("Task"); return 2 ;}));

Log ("doo: Task Result:" + await Task. run () => {Thread. sleep (1000); log ("Task"); return 3 ;}));

 

// Do not use await: multi-thread Thread Pool

ThreadPool. QueueUserWorkItem (_ =>

{

Thread. Sleep (1000 );

Console. WriteLine ("ThreadPool. QueueUserWorkItem ");

});

 

// Do not use await: multi-thread Task

Task. Run () =>

{

Thread. Sleep (1000 );

Console. WriteLine ("Task. Run ");

});

}

 

We have added multi-thread execution without await, respectively using ThreadPool and Task. The entire program will output the following results:

1: test: Before await

1: Main: After test is called

3: Task

3: doo: Task result: 1

4: Task

4: doo: Task result: 2

3: Task

3: doo: Task result: 3

3: test: After await

Task. Run

ThreadPool. QueueUserWorkItem

 

Multithreading without await completely disconnects from await tasks in the test method, and runs after await of test.

 

In addition, Visual Studio will give the following warning to the Task. Run code:



 

Tip: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.

That is to say, if await is not added, the current method will continue to be executed until the end, because we are currently doing a test in the async method without await, huh, huh.

 

 

You may ask, why do you want to use this method to return tasks from another async method of await? We have been discussing the async Method for returning tasks. I think the async Method for returning tasks <T> can better explain this problem.

 

Next we will change the above Code to a similar async method that returns the Task <int> for execution, then the doo method returns the Task <T>, he sums up the results of the three awaited tasks in his method and returns the results as the results of the Task returned by him. Then output the results returned by doo in the test method.

 

Complete code:

Static void Main (string [] args)

{

Test ();

Log ("Main: After test is called ");

Thread. Sleep (Timeout. Infinite );

}

 

// Async is not allowed for the Main method, so we use await in this method.

Static async void test ()

{

Log ("test: Before await ");

Console. WriteLine ("doo result: {0}", await doo ());

Log ("test: After await ");

}

 

// Return The async method of the Task

Static async Task <int> doo ()

{

Var res1 = await Task. Run () => {Thread. Sleep (1000); log ("awaited Task1 execution"); return

Var res2 = await Task. Run () => {Thread. Sleep (1000); log ("awaited Task2 execution"); return

Var res3 = await Task. Run () => {Thread. Sleep (1000); log ("awaited Task3 execution"); return

 

// Do not use await: multi-thread Thread Pool

ThreadPool. QueueUserWorkItem (_ =>

{

Thread. Sleep (1000 );

Console. WriteLine ("ThreadPool. QueueUserWorkItem ");

});

 

// Do not use await: multi-thread Task

Task. Run () =>

{

Thread. Sleep (1000 );

Console. WriteLine ("Task. Run ");

});

 

Return res1 + res2 + res3;

}

 

// Output method: display the ManagedThreadId of the current thread

Static void log (string msg)

{

Console. WriteLine ("{0 }:{ 1}", Thread. CurrentThread. ManagedThreadId, msg );

}

 

First look at the results:

1: test: Before await

1: Main: After test is called

3: awaited Task1 execution

4: awaited Task2 execution

4: awaited Task3 execution

Doo result: 6

4: test: After await

ThreadPool. QueueUserWorkItem

Task. Run

 

 

Like the previous example of returning a Task, when the await doo method returns a Task in the test method, the awaited Task in doo is first waited, the threads without awaited are not waited. Why? (that is, the question left above )? The following is an example of the returned Task <int>:

In the Task returned by await doo in test, we need the result, and the result is other awaited results included in the method, it can be understood as the subresult of the being. Therefore, your own results require other results. Therefore, you must wait for these results to be returned. Therefore, the results of the await doo method of the test method will also wait for await in all doo, regardless of the multi-thread execution of non-await in other doo (of course, technically speaking, it is impossible, because async/await can rely entirely on the compiler ).


From Mgen

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.