5

私は、BlockingCollection{T}1 つのスレッドだけで満たされ、1 つのスレッドだけで消費される を使用しています。アイテムの生産と消費は正常に機能します。問題は、この操作の最後にあります。タスクは (予想どおり) でブロックされGetConsumingEnumerableます。CompleteAddingタスクを呼び出した後、 を破棄しBlockingCollection、例外なく終了します。ここまでは順調ですね。

これで、にアイテムを追加するスレッドができましたBlockingCollection。このスレッドは、テストしIsAddingCompletedてからアイテムを追加する必要があります。IsAddingCompletedしかし、項目の要求と追加の間には競合状態があります。- メソッドがありTryAddますが、追加が既に完了している場合は例外も発生します。

追加のロックなしで完了した項目または追加のテストを追加するにはどうすればよいですか? なぜTryAdd例外をスローするのですか? false追加が完了していれば返却OKです。

非常に単純化されたコードは次のようになります。

private BlockingCollection<string> _items = new BlockingCollection<string>();

public void Start()
{
    Task.Factory.StartNew(
        () =>
            {
                foreach (var item in this._items.GetConsumingEnumerable())
                {
                }

                this._items.Dispose();
            });

    Thread.Sleep(50); // Wait for Task

    this._items.CompleteAdding(); // Complete adding
}

public void ConsumeItem(string item)
{
    if (!this._items.IsAddingCompleted)
    {
        this._items.Add(item);
    }
}

はい、項目を追加する機会がほとんどなく、foreach ループが通知しないため、このコードが意味をなさないことはわかっています。消費するタスクは私の問題には関係ありません。

問題はConsumeItem-method に示されています。+の周りConsumeItemに追加のロック (セマフォ) を追加することはできますが、このパフォーマンスへの影響を回避しようとします。CompleteAddingDispose

例外なくアイテムを追加するにはどうすればよいですか? アイテムの紛失は、追加が完了していれば問題ありません。

4

0 に答える 0