这个章节我我的感受意义不大,使用现有的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);