1

私にはプロデューサーとコンシューマーの2つのスレッドがあります。

プロデューサーは常に何かを生産しているとは限りません。ただし、消費者は、利用可能になり次第、消費する必要があります。

プロデューサースレッドはループで動作し、結果をに入れますConcurrentQueue。コンシューマースレッドは、システムが無効になったときにwhile (!disposing)呼び出すループにあります。メソッドがfalseを返す場合にもAutoResetEvent.WaitOne呼び出すことを検討しました。これは、キューにアイテムが残っていない場合にのみ発生するはずです。AutoResetEvent.WaitOneConcurrentQueue.TryDequeue

ただし、これを行うと、次の実行が行われたときにデッドロックが発生する可能性があります。

  1. エンキュー
  2. TryDequeueはtrueを返します
  3. TryDequeueはfalseを返します
  4. エンキュー
  5. WaitOne

これは、このスニペットの可能性です。

while (this.isDisposing == 0)
{
    if (this.isEnabled == 0)
    {
        this.signal.WaitOne();
    }

    object item;
    if (!this.queue.TryDequeue(out item))
    {
        this.signal.WaitOne();
        continue;
    }

    this.HandleItem(item);
}

ロックを使用せずにこれを行う適切な方法は何ですか?

4

2 に答える 2

1

ここでBlockingCollectionを使用するとよいと思います。キューにデータが入るまで効率的に待機します。これをConcurrentQueueと組み合わせることができると思います。http://msdn.microsoft.com/en-us/library/dd267312.aspxを参照してください

于 2012-09-24T13:56:13.710 に答える
0

ここでの問題は、スレッドの一時停止がほとんどすべてのオペレーティングシステムでカーネルレベルのイベントであるということです。私がFibersで考えているWindowsは、ユーザーレベルの一時停止/一時停止解除を許可しますが、私が知っているのはそれだけです。

それで、あなたはあなたのキューと一緒にロックレスに動き回っています、しかしあなたはそもそもキューに何かがあるときどのように合図しますか?

シグナリングは睡眠を意味します-そしてそれが問題です。ロックフリーのシグナリングを行うことはできますが、待っていると、WaitForEvent()と同等のOSを呼び出す必要があります。これは、OSが提供する低速のメカニズムを使用したくないため問題です。

基本的に、これに対するOSのサポートはまだないか、ごくわずかです。

于 2012-09-28T13:51:20.613 に答える