【问题标题】:Process stack items in several threads在多个线程中处理堆栈项
【发布时间】:2013-03-22 08:15:15
【问题描述】:

我有一个ConcurrentStack,其中的每一项都是指向某个网络资源的 URL。另外我有 N 个线程(实际上是 Tasks),每个线程从堆栈进程中弹出一个项目,并根据某些标准将结果(结果是集合)添加到此堆栈或其他输出队列中。应该这样做,直到堆栈变空。

识别此过程结束并停止此任务的更优雅的方法是什么?换句话说,如何识别栈是空的,并且没有执行任务会向栈中添加更多的项

【问题讨论】:

  • 您在描述消费者的工作方式,但您的问题是关于生产者的。

标签: c# multithreading c#-4.0 concurrency


【解决方案1】:

终止条件似乎是当所有从堆栈中读取的任务都全部等待一个项目被堆积到堆栈中。当然,只有当您为您的任务提供一种被动等待该事件的方法时,才会发生这种情况。正如其他答案所建议的那样,您可以在 ConcurrentStack 类之上使用 BlockingCollection 来实现同步。

关于终止,最简单的方法是让一个任务(终止任务)等待该条件,所有其他任务操作一个表示等待任务数量的整数,在阻塞集合之前递增它,并在当获得一个物品。当该数字达到堆栈的可能读取器总数时,当前尝试获取项目的任务会在阻塞集合之前触发条件变量,这将唤醒终止线程。

【讨论】:

    【解决方案2】:

    由于您使用的是实现IProducerConsumerCollection 的 ConcurrentStack,因此您可以用BlockingCollection 包装它(通过使用this constructor 创建一个)。这提供了一个CompleteAdding() 方法,允许您指示数据的结束。

    底层的 IProducerConsumerCollection 将用于存储项目,因此它的行为仍然类似于堆栈,因为它是 LIFO。

    您需要切换到使用GetConsumingEnumerable() 重载之一来使用数据。我发现这是处理优雅任务终止的最优雅和最强大的方式。

    也许这对你有用?

    【讨论】:

    • 感谢您的回答,我不知道将 BlockingCollection 扩展为堆栈的可能性,但是我所有的线程都不知道是否该调用 CompleteAdding,因为没有人知道其他人是否会添加更多项目
    • something 必须知道 - 并且必须调用 CompleteAdding()
    猜你喜欢
    • 1970-01-01
    • 2015-09-08
    • 2017-11-18
    • 1970-01-01
    • 2015-04-29
    • 1970-01-01
    • 2014-09-14
    • 2015-11-11
    • 1970-01-01
    相关资源
    最近更新 更多