0

BlockingCollection を使用して Producer/Consumer パターンを実装しましたが、期待どおりにブロックしていないようです。

Web カメラからフレームを受信し、BlockingCollection に追加するスレッドが 1 つあります。

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 をスローして、プルしているフレームが他の場所で使用されていることを通知する傾向があります。

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

常にすぐに発生するとは限りませんが、キューが空またはほぼ空である場合にのみ発生することに気付きました (つまり、コンシューマーがプロデューサーよりも高速です)。最初に追加された画像または最後に撮った画像。なぜこれが起こっているのでしょうか?

4

1 に答える 1

0

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

解決策の 1 つは、呼び出しをNewFrame queue.Add(image);に移動することです( video_NewFrame)。Runこれにより、イベント ハンドラーが処理を終了するまで、 がそれを認識できないことが保証されます (イベント ハンドラーがそれへの参照を保存していないと仮定します)。

于 2012-03-24T03:30:40.137 に答える