C # Task-Based asynchronous programming mode,

Source: Internet
Author: User

C # Task-Based asynchronous programming mode,

Bytes.
1. Continue the task

  

Private async static void CallerWithAsync () {string result = await GreetingAsync ("Stephen"); Console. writeLine (result);} static Task <string> GreetingAsync (string name) {return Task. run <string> () => {Thread. sleep (10000); return name;});} The GreetingAsync method returns a Task <string> object. The Task <string> object contains information about Task creation and is saved to Task completion. The ContinueWith method of the Task class defines the code called after the Task is completed. Private static void CallerWithContinuationTask () {var t1 = GreetingAsync ("Stephen"); t1.ContinueWith (t => {string result = t. result; Console. writeLine (result );});}

Because await is not used, the thread does not wait in the method, and the code of CallerWithContinuationTask () is executed. No longer ContinueWith will wait here, so a foreground thread is required. Otherwise, the thread will be closed.

Ii. Synchronization Context
The CallerWithAsync and CallerWithContinuationTask methods use different threads at different stages of the method.

  

static Task<string> GreetingAsync(string name)        {          return Task.Run<string>(() =>            {                Thread.Sleep(10000);              Console.WriteLine("running greetingasync in thread {0} and task {1}", Thread.CurrentThread.ManagedThreadId, Task.CurrentId);              return name;            });        }        private async static void CallerWithAsync()        {          Console.WriteLine("started CallerWithAsync in thread {0} and task {1}", Thread.CurrentThread.ManagedThreadId, Task.CurrentId);          string result = await GreetingAsync("Stephanie");          Console.WriteLine(result);          Console.WriteLine("finished GreetingAsync in thread {0} and task {1}", Thread.CurrentThread.ManagedThreadId, Task.CurrentId);        }                private static void CallerWithContinuationTask()        {          Console.WriteLine("started CallerWithContinuationTask in thread {0} and task {1}", Thread.CurrentThread.ManagedThreadId, Task.CurrentId);          var t1 = GreetingAsync("Stephanie");          t1.ContinueWith(t =>            {              string result = t.Result;              Console.WriteLine(result);              Console.WriteLine("finished CallerWithContinuationTask in thread {0} and task {1}", Thread.CurrentThread.ManagedThreadId, Task.CurrentId);            });        }

 



With the async and await keywords, after await is complete, you can access the UI thread without any processing. By default, the generated code converts the thread to a thread with a synchronization context. The thread that calls the Asynchronous Method is assigned to the synchronization context. After await is completed, the execution will continue.
If you do not use the same synchronization context, you must call ConfigureAwait (false) of the Task class. For example, for a WPF application, the code after its await does not have any code that uses the UI element. In this case, it is faster to switch to the synchronization context.
String s1 = await GreetingAsync ("Stephen"). ConfigureAwait (false );

Iii. Use multiple asynchronous Methods
In an asynchronous method, one or more asynchronous methods can be called. Writing code depends on whether the result of an asynchronous method depends on another Asynchronous Method.
  1. Call asynchronous methods in order
In the following example, the second asynchronous method depends on the result of the first Asynchronous Method, and the await keyword is very useful.
Private async static void MultipleAsyncMethods ()
{
String s1 = await GreetingAsync ("Stephen ");
String s2 = await GreetingAsync (s1 );
Console. WriteLine ("Finished both methods. \ n Result 1: {0} \ n Result 2: {1}", s1, s2 );
}

  2. Use a bundle
If the second Asynchronous Method is independent of the first method, each Asynchronous Method may not use await, but assign the returned results of each Asynchronous Method to the Task variable, which will run faster.
Private async static void MultipleAsyncMethodsWithCombinators1 ()
{
Task <string> t1 = GreetingAsync ("Stephen ");
Task <string> t2 = GreetingAsync ("Matthias ");
Await Task. WhenAll (t1, t2 );
Console. WriteLine ("Finished both methods. \ n Result 1: {0} \ n Result 2: {1}", t1.Result, t2.Result );
}
Task. WhenAll aggregators can accept multiple parameters of the same type and return values of the same type.
Task. WhenAll is returned only when all input methods are completed.
WhenAny is returned when the task of one of the input methods is completed.

Task. WhenAll defines several overloaded versions. If all tasks return the same type, this type of array can be used for the results returned by await.
String [] result = await Task. WhenAll (t1, t2 );

Iv. asynchronous mode conversion
Http://www.cnblogs.com/afei-24/p/6757361.html describes the three different-step programming models.
Not all. NET Framework classes introduce new asynchronous methods in. NET 4.5. Many other classes only provide asynchronous modes of the BeginXXX and EndXXX methods. You can use the FromAsync method of the TaskFactory class, which can convert the asynchronous mode method to the task-based asynchronous mode method.
  

/Create a delegate and reference the synchronization method Greeting private static Func <string, string> greetingInvoker = Greeting; static IAsyncResult BeginGreeting (string name, AsyncCallback callback, object state) {return greetingInvoker. beginInvoke (name, callback, state);} static string EndGreeting (IAsyncResult ar) {return greetingInvoker. endInvoke (ar);} // The first two parameters of the FromAsync method are the delegate type, and the address of BeginGreeting and EndGreeting is passed in. The last two parameters are input parameters and object status parameters. Private static async void ConvertingAsyncPattern () {string r = await Task <string>. factory. fromAsync <string> (BeginGreeting, EndGreeting, "Angela", null); Console. writeLine (r );}

 

5. handle errors
If the asynchronous method is called without waiting, place the Asynchronous Method in try/catch, and no exception is caught.
  

private static void DontHandle()        {          try          {            ThrowAfter(200, "first");            // exception is not caught because this method is finished before the exception is thrown          }          catch (Exception ex)          {            Console.WriteLine(ex.Message);          }        }                static async Task ThrowAfter(int ms, string message)        {            Console.Write("xxx");          await Task.Delay(ms);          throw new Exception(message);        }

After the DontHandle method calls ThrowAfter, it will not wait here, it will continue to be executed, and no reference to the ThrowAfter method will be maintained.
Note: The Asynchronous Method that returns void will never wait. It is best to return a Task type for the Asynchronous Method.

1. Asynchronous Method Exception Handling
Use the await keyword and place it in try/catch.
  

private static async void HandleOneError()        {          try          {            await ThrowAfter(2000, "first");          }          catch (Exception ex)          {            Console.WriteLine("handled {0}", ex.Message);          }        }

 

2. Exception Handling for multiple asynchronous Methods
If you follow the following code, the second exception will not be thrown. Because the first exception has been thrown, it is directly transferred to the catch Block.
  

private static async void StartTwoTasks()        {          try          {            await ThrowAfter(2000, "first");            await ThrowAfter(1000, "second"); // the second call is not invoked because the first method throws an exception          }          catch (Exception ex)          {            Console.WriteLine("handled {0}", ex.Message);          }        }

When Task. WhenAll is used, both tasks are completed no matter whether or not an exception is thrown. Therefore, two exceptions are thrown.
However, you can only see the exception information of the first Task passed to the Task. WhenAll method. Although the second exception will be thrown, It is not displayed:
  

private async static void StartTwoTasksParallel()            {              Task t1 = null;              Task t2 = null;              try              {                t1 = ThrowAfter(2000, "first");                 t2 = ThrowAfter(1000, "second");                await Task.WhenAll(t1, t2);              }              catch (Exception ex)              {                // just display the exception information of the first task that is awaited within WhenAll                Console.WriteLine("handled {0}", ex.Message);              }            }

3. Use aggresponexception to return an exception.
Write the results returned by Task. WhenAll to a Task variable. The catch statement only retrieves exceptions of the first Task, but can access the Exception attribute of taskResult of an external Task. The Exception attribute is of the aggresponexception type. This exception type defines the InnerExceptions attribute, which contains a list of all exceptions waiting.
  

private static async void ShowAggregatedException()        {          Task taskResult = null;          try          {            Task t1 = ThrowAfter(2000, "first");            Task t2 = ThrowAfter(1000, "second");            await (taskResult = Task.WhenAll(t1, t2));          }          catch (Exception ex)          {            // just display the exception information of the first task that is awaited within WhenAll            Console.WriteLine("handled {0}", ex.Message);            foreach (var ex1 in taskResult.Exception.InnerExceptions)            {              Console.WriteLine("inner exception {0} from task {1}", ex1.Message, ex1.Source);            }          }        }

6. Cancel Asynchronous Method
If the background task may run for a long time, the task may be canceled.
Canceling a framework is based on assistance and is not mandatory. A task that has been running for a long time needs to check whether it has been canceled. In this case, the task is to clear all opened resources and end the related work.
Cancelling is based on the CancellationTokenSource class, which can be used to send cancellation requests. The request is sent to a task that references the CancellationToken class. The CancellationToken class is associated with the CancellationTokenSource class.
  

Private CancellationTokenSource cts = new CancellationTokenSource (); // Add a button to cancel a running task. Use cts. Cancel (); private void button5_Click (object sender, EventArgs e) {if (cts! = Null) cts. cancel ();} private async void button4_Click (object sender, EventArgs e) {string s = await AsyncTaskTest ();} // pass the CancellationToken parameter to the Run method of the Task class. However, you must check whether the operation has been canceled. Task <string> AsyncTaskTest () {return Task. run () => {cts. token. throwIfCancellationRequested (); Thread. sleep (5000); return "Asynchronous completion" ;}, cts. token );}

 


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.