我正在阅读C# 5.0 in nutshell
,在阅读了作者的观点之后,我对我应该采用什么感到困惑。我的要求就是说我有一个很长时间运行(计算量很大)的任务,例如,计算数百万个文件的SHA1(或其他一些)哈希,或者其他任何东西都是计算量很大并且可能需要一些时间,我应该采用什么方法来开发它(如果重要的是winforms
,使用VS 2012,C#5.0),so that I can also report progress to the user
。
以下情景会浮现在脑海中......
通过实施Task
或{{1 或让任务捕获LongRunning
上下文并发布到用户界面。
创建一个{/ 1}}方法,如
IProgess<T>
使用TPL(或PLINQ)作为
Progess<T>
使用生产者/消费者队列 真的不知道怎么办?
书中的作者说......
在池化线程上运行一个长时间运行的任务不会导致 麻烦。当你并行运行多个长时间运行的任务时 (特别是那些阻止)表现会受到影响的人。在那里面 情况下,通常有更好的解决方案 TaskCreationOptions.LongRunnging
- 如果任务是IO绑定的,可以使用TaskCompletionSource和异步函数 使用回调而不是线程来实现并发。
- 如果任务是计算绑定的,那么生产者/消费者队列可以限制这些任务的并发性,避免饥饿 其他线程和流程。
关于SynchronizationContext
作者说......
生产者/消费者队列是一个有用的结构,两者并行 编程和一般并发场景,因为它给你精确 控制一次执行多少个工作线程,这很有用 不仅限制CPU消耗,还限制其他资源。
那么,我应该不使用任务,这意味着第一个选项是什么?第二个是最好的选择吗?还有其他选择吗?如果我遵循作者的建议,并实施生产者/消费者,我将如何做到这一点(我甚至不知道如何在我的方案中开始使用生产者/消费者,如果那是最好的方法!)
我想知道是否有人遇到过这种情况,他们将如何实施?如果没有,那么最有效和/或易于开发/维护的是什么(我知道Async
这个词是主观的,但我们只考虑它的工作原理,并且效果很好!)
答案 0 :(得分:8)
真正长时间运行(计算量很大)的任务,例如,计算数百万个文件的SHA1(或其他一些)哈希
该示例显然具有繁重的CPU(散列)和I / O(文件)组件。也许这是一个非代表性的例子,但根据我的经验,即使安全散列也比从磁盘读取数据快得多。
如果你只有CPU限制工作,最好的解决方案是Parallel
或PLINQ。如果您只有I / O绑定工作,最好的解决方案是使用async
。如果你有一个更现实和复杂的场景(CPU和I / O都工作),那么你应该连接你的CPU和I / O部件与生产者/消费者队列或使用更完整的解决方案,如TPL Dataflow。
TPL Dataflow适用于并行(MaxDegreeOfParallelism
)和async
,并且在每个块之间都有一个内置的生产者/消费者队列。
混合大量I / O和CPU使用时要记住的一件事是,不同的情况会导致大量不同的性能特征。为了安全起见,您需要限制通过队列的数据,这样您就不会遇到内存使用问题。 TPL Dataflow通过BoundedCapacity
内置了对限制的支持。