1.原始的异步方法的调用
我们来看个简单的例子,在这里演示调用 WebClient.DownloadStringAsync 方法(这个方法不是 TAP),然后由 WebClient.DownloadStringCompleted 事件通知 UI 更新,这是大多数人都会用的方法。
- private void DownloadString(string address)
- {
- WebClient wc = new WebClient();
- wc.DownloadStringCompleted += (sender, e) =>
- {
- if (e.Cancelled)
- this.textBox1.Text = "Cancel";
- else if (e.Error != null)
- this.textBox1.Text = "Error";
- else
- this.textBox1.Text = e.Result;
- };
- wc.DownloadStringAsync(new Uri(address));
- }
客户端调用
- private void button_DownloadString_Click(object sender, EventArgs e)
- {
- DownloadString("https://www.google.com.tw/");
- }
这是一个很简单的例子,一旦若项目里有成千上万的通知事件跟 UI 绑在一起,维护起来会相当的痛苦。
2.将 EAP 转换成 TAP步骤
- 命名规则以 Async 为后缀
- 返回 Task 或是 Task<TResult>
- 调用 TaskCompletionSource 方法
改变 Task 状态可调用以下三个方法:SetCanceled、SetException、SetResult
- private Task<string> DownloadStringAsync(string address)
- {
- var tcs = new TaskCompletionSource<string>();
- WebClient wc = new WebClient();
- wc.DownloadStringCompleted += (sender, e) =>
- {
- if (e.Cancelled)
- tcs.SetCanceled();
- else if (e.Error != null)
- tcs.SetException(e.Error);
- else
- tcs.SetResult(e.Result);
- };
- wc.DownloadStringAsync(new Uri(address));
- return tcs.Task;
- }
客户端调用
- private async void button_DownloadStringAsync_Click(object sender, EventArgs e)
- {
- var task = DownloadStringAsync("https://www.google.com.tw/");
- await task;
- if (task.IsCanceled)
- {
- this.textBox1.Text = "Cancel";
- }
- else if (task.IsFaulted)
- {
- this.textBox1.Text = "Error";
- }
- else if (task.IsCompleted)
- {
- this.textBox1.Text = task.Result;
- }
- }
转自:http://www.it165.net/pro/html/201308/6710.html
3.微软的封装
- public static Task<byte[]> DownloadDataTask(this WebClient webClient, Uri address)
- {
- // Create the task to be returned
- var tcs = new TaskCompletionSource<byte[]>(address);
- // Setup the callback event handler
- DownloadDataCompletedEventHandler handler = null;
- handler = (sender, e) => EAPCommon.HandleCompletion(tcs, e, () => e.Result, () => webClient.DownloadDataCompleted -= handler);
- webClient.DownloadDataCompleted += handler;
- // Start the async work
- try
- {
- webClient.DownloadDataAsync(address, tcs);
- }
- catch(Exception exc)
- {
- // If something goes wrong kicking off the async work,
- // unregister the callback and cancel the created task
- webClient.DownloadDataCompleted -= handler;
- tcs.TrySetException(exc);
- }
- // Return the task that represents the async operation
- return tcs.Task;
- }
- internal class EAPCommon
- {
- internal static void HandleCompletion<T>(
- TaskCompletionSource<T> tcs, AsyncCompletedEventArgs e, Func<T> getResult, Action unregisterHandler)
- {
- // Transfers the results from the AsyncCompletedEventArgs and getResult() to the
- // TaskCompletionSource, but only AsyncCompletedEventArg's UserState matches the TCS
- // (this check is important if the same WebClient is used for multiple, asynchronous
- // operations concurrently). Also unregisters the handler to avoid a leak.
- if (e.UserState == tcs)
- {
- if (e.Cancelled) tcs.TrySetCanceled();
- else if (e.Error != null) tcs.TrySetException(e.Error);
- else tcs.TrySetResult(getResult());
- unregisterHandler();
- }
- }
- }