【发布时间】:2013-08-20 15:05:08
【问题描述】:
我正在开发的应用程序是这样组成的: 生产者任务扫描文件系统中的文本文件并将对它们的引用放入包中。 许多消费者任务同时从包中获取文件引用并读取文件(并对其内容做一些简短的工作)
我必须能够暂停和恢复整个过程。
我尝试过使用 TPL,为每个放入包中的文件 ref 创建一个任务(在这种情况下,包只是一个概念,生产者在查找文件时直接创建消费者任务)但是这样我无法控制我创建的任务,我不能(或者我不知道如何)暂停它们。我可以编写一些代码来暂停当前正在执行任务的线程,但这会破坏处理逻辑任务而不是手动创建线程的意义,不是吗?我想要类似“已经分配给物理线程的任务可以完成,但等待的逻辑任务在恢复命令之前不应启动”
我怎样才能做到这一点?可以用 TPL 完成还是我应该使用其他东西?
编辑: 您的答案都是有效的,但我的主要疑问仍未得到解答。我们正在谈论任务,如果我使用 TPL,我的生产者和我的许多消费者将是任务(对吗?)而不是线程(好吧,在执行的那一刻,任务将映射到线程上)。我发现的每一种同步机制(如评论“ManualResetEventSlim”中提出的那种)都在线程级别工作。
例如“ManualResetEventSlim”的Wait()方法的描述是“阻塞当前线程,直到当前ManualResetEventSlim被设置。”
我对任务的了解纯粹是学术性的,我不知道“现实世界”中的事情是如何运作的,但对我来说,我需要一种在任务中协调(等待/信号/...)任务的方法似乎是合乎逻辑的级别或事情可能会变得很奇怪......就像......两个任务可能映射在同一个线程上,但一个应该发出信号,另一个正在等待然后死锁。我有点困惑。这就是为什么我问我的应用是否可以使用 TPL 代替老式简单线程。
【问题讨论】:
-
是的,您必须自己创建一个暂停机制。使用例如消费者反复等待的
ManualResetEventSlim,生产者设置/重置为暂停/恢复。 -
普通的
Task总是在单个线程上执行。因此,任何适用于Threads 的同步原语也适用于Tasks。 -
@svick 如果我启动 100 个执行包含 Wait() 的相同代码的任务怎么办?根据对这个问题的接受答案stackoverflow.com/questions/14515207/… 将创建 100 个等待线程,好吗?
-
@flagg19 我认为这个答案是错误的(至少对于.Net 4.5)。但是如果你不调用
ThreadPool.SetMaxThreads(),那么是的,最终会创建100个线程。这并不理想,所以如果你不想那样,你将不得不做一些事情。要么在集合中有代表而不是Tasks,然后有有限数量的Tasks 来处理它们(你可以使用Parallel.ForEach())。另一种选择是使用a customTaskSchedulerwith limited degree of parallelism。 -
@svick 谢谢,我想我会选择“在集合中有代表而不是任务,然后处理它们的任务数量有限”
标签: c# task-parallel-library .net-4.5