【发布时间】:2013-11-23 14:06:12
【问题描述】:
我有一个进程生成工作,第二个进程使用 BlockingCollection<> 消耗该工作。当我关闭我的程序时,我需要我的消费者停止消费工作,但我仍然需要快速记录等待但尚未消费的工作。
现在,我的消费者产生了一个具有foreach (<object> in BlockingCollection.GetConsumingEnumerable()) 循环的线程。当我停止我的程序时,我的制片人会打电话给Consumer.BlockingCollection.CompleteAdding()。我发现我的消费者继续处理队列中的所有内容。
谷歌搜索问题告诉我我需要使用CancellationToken。所以我试了一下:
private void Process () { // This method runs in a separate thread
try {
foreach (*work* in BlockingCollection.GetConsumingEnumerable(CancellationToken)) {
// Consume
}
}
catch (OperationCancelledException) {
foreach (*work* in BlockingCollection.GetConsumingEnumerable()) {
// quickly log
}
}
}
我的制作人有:
private CancellationTokenSource StopFlag = new CancellationTokenSource ();
MyConsumer.CancellationToken = StopFlag.Token;
// Make the consumer spawn it's consuming thread...
StopFlag.Cancel ();
MyConsumer.BlockingCollection.CompleteAdding ();
当我尝试这个时,没有任何迹象表明 OperationCancelledException 曾经发生过。
This question 试图解释取消令牌的使用,但似乎没有正确使用它。 (论点:如果它有效,那么它“足够正确”。)this question 似乎与我的问题完全相同,但没有示例。 (同样here。)
所以重申一下:我如何在BlockingCollection.GetConsumingEnumerable() 上正确使用CancellationToken,但需要注意的是,在使用不同的方法取消队列后,我需要处理队列中的剩余项目?
(我认为我的问题集中在正确使用 CancellationToken 上。我的测试均未表明该进程实际上已被取消。(StopFlag.IsCancellationRequested 始终等于 false。))
【问题讨论】:
-
GetConsumingEnumerable将等待添加更多项目。在catch内使用集合本身的foreach。 -
我很想试试,Romoku!我怎么去呢?我使用了简单的ctor:
public BlockingCollection<cOrder> OrderQueue = new BlockingCollection<cOrder> (); -
您需要检查取消令牌。 CancellationToken.IsCancellationRequeste 在您的情况下,如果为 true,则仍会处理但记录而不是处理。 msdn.microsoft.com/en-us/library/dd997289.aspx
标签: c# .net multithreading blockingcollection