《C#并行编程高级教程》第9章 异步编程模型 笔记

这个章节我个人感觉意义不大,使用现有的APM(异步编程模型)和EAP(基于时间的异步模型)就很够用了,针对WPF和WinForm其实还有一些专门用于UI更新的类。
但是出于完整性,还是将一下怎么使用.NET4的并行扩展,也就是一直在使用Task模型来处理异步问题。有一个特别好处是,当有大量并发的IO操作时会有更好的效果。
大量并发的IO操作的含义是类似如下
private List<Task<int>> tasks;
有一堆的task,其中的每一个task都是一个异步的IO操作。

APM->Task

而一个整和APM的task产生方法如下
Task<int> task =
    Task<int>.Factory.FromAsync(
    stream.BeginRead, stream.EndRead,
    data, 0, data.Length, null,
    TaskCreationOptions.None);
另外不需要调用task的Start方法

EAP->Task

使用TaskCompletionSource<TResult>可以将一个EAP操作表示为一个Task<TResult>
使用TaskCompletionSource的几个方法可以尝试将底层的Task转换到某个特定的状态
TrySetCanceled:task转换成TaskStatusCanceled
SetException:task转换成TaskStatusFaulted
TrySetResult:task转换成TaskStatusRanToCompletion
 
下面以WebClient.DownloadFileAsync为例,演示如何将一个EAP的操作处理成一个Task对象
var tcs = new TaskCompletionSource<string>();
 
var wc = new WebClient();
 
AsyncCompletedEventHandler handler  =
    (hSender, hE) =>
    {
        if (hE.Error != null)
        {
            tcs.TrySetException(hE.Error);
        }
        else if (hE.Cancelled)
        {
            tcs.TrySetCanceled();
        }
        else
        {
            tcs.TrySetResult(fileName);
        }
        wc.DownloadFileCompleted -= handler;
    };
 
wc.DownloadFileCompleted += handler;
 
try
{
    wc.DownloadFileAsync(address, fileName);
}
catch (Exception ex)
{
    wc.DownloadFileCompleted -= handler;
    tcs.TrySetException(ex);
}
 
Task task = tcs.Task;

UI的更新

不论是WPF还是WinForm,UI控件只能在UI线程进行操作。他们都有各自的多种方案。
而使用Task模型的方案是使用一个TaskScheduler.FromCurrentSynchronizationContext();获取一个TaskScheduler,使用TaskScheduler执行的Task就是在UI线程下的。
var uiScheduler =
    TaskScheduler.FromCurrentSynchronizationContext();
var builderTask = //...一个不修改UI的任务
builderTask.ContinueWith(
        (t) =>
        {
            //..在这里进行UI的更新
        }, uiScheduler);
 
 




原文地址:https://www.cnblogs.com/atskyline/p/3247090.html