我有一个问题,关于如何自定义新的async/ await关键字和TaskC#4.5中的类.
首先是了解我的问题的一些背景:我正在开发一个具有以下设计的框架:
Update()枚举列表并查看某些"事物"是否需要执行的功能.基本上它就像一个大线程的sheduler.为简化起见,我们假设"要做的事情"是true当它们"完成"时返回布尔值的函数(并且不应该被称为下一个更新),并且false当sheduler应该在下次更新时再次调用它们时.Update()函数中迭代几个hundret事件.一个例子:
Future f1, f2;
bool SomeThingToDo() // returns true when "finished"
{
if (f1 == null)
f1 = Remote1.CallF1();
else if (f1.IsComplete && f2 == null)
f2 = Remote2.CallF2();
else if (f2 != null && f2.IsComplete)
return true;
return false;
}
Run Code Online (Sandbox Code Playgroud)
现在,这一切听起来像awefull async和await的C#5.0可以帮助我在这里.我没有100%完全理解它在幕后做了什么(任何好的参考?),但是当我从一些我已经看过的谈话中得到它时,它完全符合我想要的这个非常简单的代码:
async Task SomeThingToDo() // returning task is completed when this is finished.
{
await Remote1.CallF1();
await Remote2.CallF2();
}
Run Code Online (Sandbox Code Playgroud)
但我无法找到一种方法来编写我的Update()函数来实现这样的事情.async并且await似乎想要使用Task- 类反过来似乎需要真正的线程?
迄今为止我最接近的"解决方案":
第一个线程(正在运行SomeThingToDo)只调用它们的函数一次并存储返回的任务并测试每个Update()任务是否完成.
Remote1.CallF1返回一个新的Task,其中一个空的Action作为构造函数参数,并记住返回的任务.当F1实际完成时,它会调用RunSynchronously()任务将其标记为已完成.
在我看来,这似乎是对任务系统的歪曲.除此之外,它会IsComplete在两个线程之间创建共享内存(Task的布尔值),如果可能的话,我希望用我们的远程Messanging系统替换它们.
最后,它没有解决我的问题,因为它不适用于SomeThingToDo上面的类似await的实现.似乎异步函数返回的自动生成的Task对象立即完成?
最后我的问题:
Task<T>吗?Task没有任何与"阻塞"和"线程"相关的东西吗?async和await?Eri*_*ert 13
我没有100%完全理解它在引擎盖下做了什么 - 任何好的参考?
回到我们设计Mads时,Stephen和我在MSDN杂志的各个不同层面上写了一些文章.链接在这里:
http://blogs.msdn.com/b/ericlippert/archive/2011/10/03/async-articles.aspx
从我的文章开始,然后是Mads's,然后是Stephen's.
似乎异步函数返回的自动生成的Task对象立即完成?
不,它们在方法体中的代码返回或抛出时完成,与任何其他代码相同.
我可以挂钩到async/await来使用我自己的实现而不是
Task<T>吗?
其中一种方法包含一个await必须返回void,Task或Task<T>.但是,只要您可以调用它,等待的表达式就可以返回任何类型GetAwaiter().那不一定是一个Task.
如果那是不可能的,我可以使用任何没有任何与"阻塞"和"线程"相关的任务吗?
绝对.一个Task刚刚代表工作,将在未来完成.虽然这项工作通常在另一个线程上完成,但没有要求.
我可以挂钩到async/await来使用我自己的实现而不是Task吗?
是.
如果那是不可能的,我可以使用任何没有任何与"阻塞"和"线程"相关的任务吗?
是.
什么好的参考我写异步和等待时究竟发生了什么?
是.
我不鼓励你问是/否问题.你可能不只是想要是/否答案.
async和await似乎想要使用Task - 这反过来似乎需要真正的线程?
不,那不是真的.A Task表示可以在将来某个时刻完成的事情,可能会产生结果.它有时会在另一个线程一些计算的结果,但它并不需要如此.它可以是未来某个时刻发生的任何事情.例如,它可能是IO操作的结果.
Remote1.CallF1返回一个新的Task,其中一个空的Action作为构造函数参数,并记住返回的任务.当F1实际完成时,它会调用RunSynchronously()任务将其标记为已完成.
所以你在这里缺少的是TaskCompletionSource课程.有了这个缺失的拼图,很多东西都应该适合.你可以创建TCS对象,将Task它的Task属性传递给...任何人,然后使用该SetResult属性来表示它的完成.这样做不会导致创建任何其他线程,也不会使用线程池.
请注意,如果您没有结果而只是想要Task而不是a Task<T>那么只需使用TaskCompletionSource<bool>沿着这些线的某个或某些东西然后SetResult(false)或任何适当的东西.通过转换Task<bool>为a,Task您可以从公共API隐藏该实现.
这也应该提供您提出的前两个问题的"如何"变体,而不是您提出的"我可以"版本.你可以使用a TaskCompletionSource生成一个任务,只要你说它就完成了,使用你想要的任何异步构造,这可能涉及或不涉及使用额外的线程.
回答你的问题:
我可以挂钩到async/await来使用我自己的实现而不是Task吗?
是.你可以等待任何事情.但是,我不推荐这个.
如果那是不可能的,我可以使用任何没有任何与"阻塞"和"线程"相关的任务吗?
这种Task类型代表着未来.它不一定在线程上"运行"; 它可以表示下载完成或计时器到期等.
什么好的参考我写异步和等待时究竟发生了什么?
如果你的意思是代码转换,这篇博文有一个很好的并排.它的细节并不是100%准确,但它足以写一个简单的定制等待者.
如果你真的想扭转async你的出价,Jon Skeet的eduasync系列是最好的资源.但是,我真的不建议你在制作中这样做.
您可能会发现我async/ await介绍有用,作为async概念的介绍和推荐的使用方法.在官方的MSDN文档也异常优秀.
我确实写了可能适合你情况的课程AsyncContext和AsyncContextThread课程 ; 它们为async/ awaitmethods 定义了单线程上下文.您可以AsyncContextThread使用其Factory属性将工作(或发送消息)排队.
| 归档时间: |
|
| 查看次数: |
989 次 |
| 最近记录: |