BlockingCollection,竞争条件?

时间:2012-03-24 02:35:29

标签: c# multithreading blockingcollection

我使用BlockingCollection实现了Producer / Consumer模式,但它似乎并没有像我期望的那样阻塞。

我有一个线程从网络摄像头接收帧并将它们添加到BlockingCollection

private void video_NewFrame(object sender, NewFrameEventArgs eventArgs) {
    image = (Bitmap)eventArgs.Frame.Clone();
    queue.Add(image);
    if (NewFrame != null)
        NewFrame(this, new NewFrameEventArgs(image)); //invoke the event for display
}

在另一个线程中,我有一个对集合的引用并使用

处理帧
public void Run() {
    foreach (Bitmap bmp in queue.GetConsumingEnumerable()) {
        // process bitmap

但是,正如你在下面看到的那样,它往往会抛出一个InvalidOperationException,告诉我正在拉动的Frame正在其他地方使用。

img http://i17.photobucket.com/albums/b52/orubap/2012-03-24_020858.png

它并不总是立即发生,但我注意到它只发生在队列为空或接近空时(即消费者比生产者更快)所以我猜它与第一个有关添加了图像或拍摄的最后一张图像。任何想法为什么会这样?

1 个答案:

答案 0 :(得分:0)

执行video_NewFrame的线程在将图像传递给NewFrame事件处理程序时使用该图像。由于这与Run同时运行,因此没有什么能阻止两个线程同时访问image。 (只有在Run事件处理程序正在处理图像时NewFrame使图像出列时才会发生这种情况,这解释了为什么只有在队列为空或几乎为空时才能看到它。)

一个修复可能是在 NewFrame之前将呼叫转移到queue.Add(image); (在video_NewFrame中)。这将确保Run在事件处理程序完成之前无法看到它(假设事件处理程序不存储对它的引用)。