利用TaskCompletionSource将EAP转换成TAP

 

 

1.原始的异步方法的调用

 

我们来看个简单的例子,在这里演示调用 WebClient.DownloadStringAsync 方法(这个方法不是 TAP),然后由 WebClient.DownloadStringCompleted 事件通知 UI 更新,这是大多数人都会用的方法。

 

  1. private void DownloadString(string address)
  2. {
  3.     WebClient wc = new WebClient();
  4.     wc.DownloadStringCompleted += (sender, e) =>
  5.     {
  6.         if (e.Cancelled)
  7.             this.textBox1.Text = "Cancel";
  8.         else if (e.Error != null)
  9.             this.textBox1.Text = "Error";
  10.         else
  11.             this.textBox1.Text = e.Result;
  12.     };
  13.  
  14.     wc.DownloadStringAsync(new Uri(address));
  15. }

客户端调用

 

  1. private void button_DownloadString_Click(object sender, EventArgs e)
  2. {
  3.     DownloadString("https://www.google.com.tw/");
  4. }

这是一个很简单的例子,一旦若项目里有成千上万的通知事件跟 UI 绑在一起,维护起来会相当的痛苦。

 

2.将 EAP 转换成 TAP步骤

 

  • 命名规则以 Async 为后缀
  • 返回 Task 或是 Task<TResult>
  • 调用 TaskCompletionSource 方法

 

改变 Task 状态可调用以下三个方法:SetCanceled、SetException、SetResult

  1. private Task<string> DownloadStringAsync(string address)
  2. {
  3.     var tcs = new TaskCompletionSource<string>();
  4.     WebClient wc = new WebClient();
  5.     wc.DownloadStringCompleted += (sender, e) =>
  6.     {
  7.         if (e.Cancelled)
  8.             tcs.SetCanceled();
  9.         else if (e.Error != null)
  10.             tcs.SetException(e.Error);
  11.         else
  12.             tcs.SetResult(e.Result);
  13.     };
  14.  
  15.     wc.DownloadStringAsync(new Uri(address));
  16.     return tcs.Task;
  17. }

 

客户端调用

  1. private async void button_DownloadStringAsync_Click(object sender, EventArgs e)
  2. {
  3.     var task = DownloadStringAsync("https://www.google.com.tw/");
  4.     await task;
  5.     if (task.IsCanceled)
  6.     {
  7.         this.textBox1.Text = "Cancel";
  8.     }
  9.     else if (task.IsFaulted)
  10.     {
  11.         this.textBox1.Text = "Error";
  12.     }
  13.     else if (task.IsCompleted)
  14.     {
  15.         this.textBox1.Text = task.Result;
  16.     }
  17. }

 

转自:http://www.it165.net/pro/html/201308/6710.html

 

3.微软的封装

 

  1. public static Task<byte[]> DownloadDataTask(this WebClient webClient, Uri address)
  2. {
  3.     // Create the task to be returned
  4.     var tcs = new TaskCompletionSource<byte[]>(address);
  5.  
  6.     // Setup the callback event handler
  7.     DownloadDataCompletedEventHandler handler = null;
  8.     handler = (sender, e) => EAPCommon.HandleCompletion(tcs, e, () => e.Result, () => webClient.DownloadDataCompleted -= handler);
  9.     webClient.DownloadDataCompleted += handler;
  10.  
  11.     // Start the async work
  12.     try
  13.     {
  14.         webClient.DownloadDataAsync(address, tcs);
  15.     }
  16.     catch(Exception exc)
  17.     {
  18.         // If something goes wrong kicking off the async work,
  19.         // unregister the callback and cancel the created task
  20.         webClient.DownloadDataCompleted -= handler;
  21.         tcs.TrySetException(exc);
  22.     }
  23.  
  24.     // Return the task that represents the async operation
  25.     return tcs.Task;
  26. }

 

  1. internal class EAPCommon
  2. {
  3.     internal static void HandleCompletion<T>(
  4.         TaskCompletionSource<T> tcs, AsyncCompletedEventArgs e, Func<T> getResult, Action unregisterHandler)
  5.     {
  6.         // Transfers the results from the AsyncCompletedEventArgs and getResult() to the
  7.         // TaskCompletionSource, but only AsyncCompletedEventArg's UserState matches the TCS
  8.         // (this check is important if the same WebClient is used for multiple, asynchronous
  9.         // operations concurrently). Also unregisters the handler to avoid a leak.
  10.         if (e.UserState == tcs)
  11.         {
  12.             if (e.Cancelled) tcs.TrySetCanceled();
  13.             else if (e.Error != null) tcs.TrySetException(e.Error);
  14.             else tcs.TrySetResult(getResult());
  15.             unregisterHandler();
  16.         }
  17.     }
  18. }
posted @ 2015-09-23 09:52  _DN  阅读(365)  评论(0编辑  收藏  举报