jam*_*o00 12 c# mono continuations design-patterns coroutine
目前,我有大量的C#计算(方法调用)驻留在将按顺序运行的队列中.每次计算都会使用一些高延迟服务(网络,磁盘......).
我打算使用Mono协程来允许计算队列中的下一次计算继续,而先前的计算正在等待高延迟服务返回.但是,我更喜欢不依赖Mono协同程序.
是否存在可在纯C#中实现的设计模式,这使我能够在等待高延迟服务返回时处理其他计算?
谢谢
更新:
我需要执行大量(> 10000)任务,每个任务都将使用一些高延迟服务.在Windows上,您无法创建那么多线程.
更新:
基本上,我需要一个设计模式来模拟Stackless Python(http://www.stackless.com/)中的tasklet的优点(如下所示)
您可以使用IEnumerable模拟协作微线程.不幸的是,这不适用于阻止API,因此您需要查找可以轮询的API,或者具有可用于发送信号的回调的API.
考虑一种方法
IEnumerable Thread ()
{
//do some stuff
Foo ();
//co-operatively yield
yield null;
//do some more stuff
Bar ();
//sleep 2 seconds
yield new TimeSpan (2000);
}
Run Code Online (Sandbox Code Playgroud)
C#编译器会将其解包到状态机中 - 但外观是合作微线程的外观.
这种模式非常简单.您实现了一个"调度程序",它保存所有活动IEnumerator的列表.当它循环遍历列表时,它使用MoveNext()"运行"每个列表.如果MoveNext的值为false,则线程已结束,并且调度程序将其从列表中删除.如果是,则调度程序访问Current属性以确定线程的当前状态.如果它是TimeSpan,则线程希望休眠,并且调度程序将其移动到某个队列,当睡眠时间结束时,该队列可以刷回主列表.
您可以使用其他返回对象来实现其他信号机制.例如,定义某种WaitHandle.如果线程产生其中一个,则可以将其移动到等待队列,直到发出句柄信号.或者你可以通过产生一组等待句柄来支持WaitAll.你甚至可以实现优先事项.
我在大约150LOC中做了一个简单的调度程序实现,但我还没有完成对代码的博客.它适用于我们的PhyreSharp PhyreEngine包装器(不会公开),在我们的一个演示中,它可以很好地控制几百个字符.我们从Unity3D引擎借用了这个概念 - 他们有一些在线文档可以从用户的角度来解释它.
.NET 4.0附带了对Task并行性的广泛支持:
我建议使用线程池使用从任务队列中提供的活动任务列表,以可管理的批次一次从队列中执行多个任务.
在这种情况下,您的主工作线程最初会将N个任务从队列中弹出到活动任务列表中以分派到线程池(最有可能使用QueueUserWorkItem),其中N表示不会使线程池重载的可管理量,bog您的应用程序因线程调度和同步成本而下降,或由于每项任务的I/O内存开销合并而占用可用内存.
只要任务向工作线程发出完成信号,就可以将其从活动任务列表中删除,并从任务队列中添加下一个要执行的任务.
这将允许您从队列中拥有一组滚动的N个任务.您可以操纵N来影响性能特征,并找到在您的特定情况下最佳的特性.
由于您最终受到硬件操作(磁盘I/O和网络I/O,CPU)的瓶颈,我认为更小更好.在磁盘I/O上工作的两个线程池任务很可能不会比一个更快地执行.
您还可以通过将活动任务列表的大小和内容限制为特定类型的特定任务类型来实现灵活性.例如,如果您在具有4个内核的计算机上运行,您可能会发现性能最高的配置是同时运行的四个CPU绑定任务以及一个磁盘绑定任务和一个网络任务.
如果您已将一项任务归类为磁盘IO任务,则可以选择等到它完成后再添加另一个磁盘IO任务,并且您可以选择同时安排CPU绑定或网络绑定任务.
希望这是有道理的!
PS:你对任务的顺序有任何依赖吗?