.net 4.0 上的 BlockingCollection 非常独特的例外
我正在使用 BlockingCollection
作为生产者消费者模式,但我遇到了一个例外,我想为此写一个专利 - 谷歌中只有两个结果! 期望是“CompleteAdding 不能与集合中的添加同时使用”,当我在 BlockingCollection 上进行 TryAdd
时,就会发生这种情况,如下所示:
public void EnqueueTask(T item)
{
if (!_cancellationTokenSource.IsCancellationRequested)
{
_workerQueue.Add(item);
}
}
在处理时调用 CompleteAdding
消费者-生产者包装类:
public void Dispose()
{
if (!_IsActive)
return;
_IsActive = false;
_cancellationTokenSource.Cancel();
_workerQueue.CompleteAdding();
// Wait for the consumer's thread to finish.
for (int i = 0; i < _workers.Length; ++i)
{
Task t1 = Task.Factory.StartNew(() =>
{
try
{
if (!_workers[i].Join(4000))
LogWriter.Trace("Failed to join thread", "ThreadFailureOnDispose");
}
catch (Exception ex)
{
OnLogged(ex.Message + ex.StackTrace);
}
});
}
// Release any OS resources.
}
微软的任何人有一个想法吗?我应该在取消之后和调用 CompleteAdding 之前睡觉吗?
i'm using the BlockingCollection
for a Producer Consumer pattern and i got an excecption i think to write a patent on it- only two results in google!
the expection is "CompleteAdding may not be used concurrently with additions to the collection" and it happens when i TryAdd
on th BlockingCollection as Follows:
public void EnqueueTask(T item)
{
if (!_cancellationTokenSource.IsCancellationRequested)
{
_workerQueue.Add(item);
}
}
the CompleteAdding
is called on the dispose of the Consumer-Producer wrapper class:
public void Dispose()
{
if (!_IsActive)
return;
_IsActive = false;
_cancellationTokenSource.Cancel();
_workerQueue.CompleteAdding();
// Wait for the consumer's thread to finish.
for (int i = 0; i < _workers.Length; ++i)
{
Task t1 = Task.Factory.StartNew(() =>
{
try
{
if (!_workers[i].Join(4000))
LogWriter.Trace("Failed to join thread", "ThreadFailureOnDispose");
}
catch (Exception ex)
{
OnLogged(ex.Message + ex.StackTrace);
}
});
}
// Release any OS resources.
}
Anyone from microsoft got an idea? should i sleep after the cancelation and before calling the CompleteAdding?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
看一下这段代码:
在
_workers[i].Join(4000)
中,i
的值并不是你想象的那样。重试:在您的版本中,捕获变量“i”并且所有任务都使用相同的变量。除了前几个之外,所有其他都会看到
i == _workers.Length
因为它们是在 for 循环完成后执行的。这是一个经典的 lambda + 捕获的 var 问题。
Look at this piece of the code:
In
_workers[i].Join(4000)
, the value ofi
is not what you think it is. Try again with:In your version, the variable 'i' is captured and all Tasks use the same var. All but the first few will see
i == _workers.Length
because they are executed after the for-loop is completed.It is a classic lambda + captured var problem.