2012-03-24 58 views
0

BlockingCollectionを使用してプロデューサ/コンシューマパターンを実装しましたが、期待通りにブロックされていないようです。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 
} 

をウェブカメラからフレームを受信し、BlockingCollection

に追加するスレッドを1つ持っているし、別のスレッドで、私はコレクションへの参照を持っていると

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

を使用してフレームを処理下に示すように、InvalidOperationExceptionがスローされて、引っ張っているフレームが他の場所で使用されていることがわかります。

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

それはいつもすぐに発生しませんが、私は、キューが空または空の近くにあるときにのみ発生気づいた(すなわち。消費者が生産者よりも高速である)ので、私はそれをだ推測しています追加された最初の画像または最後に撮影された画像と関係があります。これがなぜ起こっているのでしょうか?

+1

さて、あなたは* 2つの場所で画像を使用しているようです。 1つはコレクションのコンシューマーにあり、もう1つはイベントハンドラーです。それはおそらくあなたの問題です。 'BlockingCollection'はあなたがやっている可能性のあることを知らないので、これであなたを助けません。 – svick

答えて

0

video_NewFrameを実行するスレッドは、NewFrameイベントハンドラに渡されるときにイメージを使用しています。これはRunと同時に実行されているため、2つのスレッドが同時にimageにアクセスすることはありません。 (NewFrameイベントハンドラがそれを処理している間Runは画像をデキューするときにのみ、キューが空またはほぼ空である場合にのみ、あなたはそれを参照してください理由を説明され、発生します。)

一つの修正はNewFrameへの呼び出しを移動するかもしれませんの前、queue.Add(image);video_NewFrame)。これにより、イベントハンドラがイベントハンドラを終了するまで、Runがそれを見ることができなくなります(イベントハンドラに参照が格納されていないと仮定して)。

+0

あなたとsvickが正しいですが、問題はイベントハンドラです。私はNewFrameEventArgsがコピーをオフにして、そのサブスクライバへの参照ではないと思っていました。キューに追加した場合でも、NewFrameを最初に起動した場合でも、2番目の操作で同じ参照が使用されないように、クローンを使用していることを確認するという解決策がありました。ありがとうございました! – hspim

関連する問題