• 利用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. }
  • 相关阅读:
    在openSUSE11.1上安装和配置LAMP(Apache/MySQL/PHP)
    正则表达式的性能?!
    RealPlayer11 for linux 64位 下载
    未能加载视图状态。
    双边贸易网 YouMeTrade.com 上线了, 欢迎大家推荐网站优化技术,也发一些我的心得.
    Sql2000分页效率之我见。
    Linq查询绑定给GridView,提示 数据源不支持服务器端的数据分页.
    控件开发笔记,鄙视写 LinkButton 那个傻蛋.
    有关SQLSERVER 中DATEDIFF函数分析
    使用SHTML更好的维护门户网站(转)
  • 原文地址:https://www.cnblogs.com/pengzhen/p/4831339.html
Copyright © 2020-2023  润新知