您的位置:首页 > 大数据 > 人工智能

Visual Studio Async CTP的实现原理浅析 - 跳出Task,构建自己的Awaiter

2011-04-01 15:26 627 查看
看完上篇之后,我们知道await关键字后面跟的是一个Task对象,虽然为了看起来很像一个实际方法,AsyncCTP类库为现有对象添加的扩展方法没有使用典型的Get/Make等字眼,更准确的说法应该是await后面应该跟的是一个Await对象,或者是一个有一个public类型的GetAwaiter()方法并且能返回Awaiter对象的对象,这里所谓的Awaiter对象和我们以往的说法稍微有些区别,因为是编译器层的语法糖,所以Awaiter对象并没有实际的意义,比如实现了一个IAwaitable之类的接口,它仅仅要求有一个BeginAwait和EndAwait方法。

看下面的代码片段:

await1000;



我们希望能异步等待1000毫秒,编译器当然毫不客气的拒绝了我们的要求,因为从1000这个数字无法获得一个Awaiter(为了简洁,后面沿用这个说法,准确的说法应该是没有从中找到BeginAwait和EndAwait方法),为了达到我们的目的,我们利用Task给int添加一个GetAwaiter方法:

publicstaticclassIntExtensions

[code]{
publicstaticTaskAwaiter<int>GetAwaiter(thisints)

{

TaskCompletionSource<int>tsc=newTaskCompletionSource<int>();

Task<int>task=tsc.Task;


tsc.TrySetResult(0);


returntask.GetAwaiter<0>();

}

}

[/code]

这样,await1000被编译器认同,我们的代码能顺利执行,但是我们还没有为Task指定执行我们需要的等待1000毫秒,所以await会马上返回。这里先不涉及Task的内容,我们使用另外一个方法,直接为Int类型实现BeginAwait和EndAwait两个方法,或者单独定义一个IntAwaiter类,上面的代码简单的修改为:


publicstaticIntAwaiterGetAwaiter(thisinti)

[code]{
returnnewIntAwaiter(i);

}

[/code]

而IntAwaiter类的定义如下:


publicclassIntAwaiter

[code]{
SynchronizationContext_UIContext=SynchronizationContext.Current;


int_Value=0;


publicIntAwaiter(inti)

{

_Value=i;

}


publicboolBeginAwait(Actioncontinuation)

{

if(SynchronizationContext.Current!=_UIContext)

{

returnfalse;

}

else

{

ThreadPool.QueueUserWorkItem((state)=>

{

Thread.Sleep(_Value);

_Value=5;

_UIContext.Send(newSendOrPostCallback((target)=>{continuation();}),null);

});

returntrue;

}

}


publicintEndAwait()

{

return_Value;

}

}

[/code]

然后我们来写几句代码测试一下:

listBox1.Items.Add(DateTime.Now);

[code]await1000;
listBox1.Items.Add(DateTime.Now);

await5000;
listBox1.Items.Add(DateTime.Now);

[/code]

结果如下:





IntAwaiter非常简单,实际上AsyncCTP中的TaskAwaiter也基本上就做了这些事,在BeginAwait中启动Task,在EndAwait中判断Task状态,如果成功完成,返回Task的Result对象,如果是Cancel或者Fault,则抛出异常。

有了前文和本文的了解,实际上如果一个应用中的异步方法是自己实现的而非像WCF一样由VS自动生成的代理类,那么完全可以在代码中处理async达到和await一样简洁的代码风格而不是让编译器来干这事,毕竟如果不是真的无法取代我不愿意带上130K的这家伙,而且Preview版无法调试await也很让人头疼。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: