私は、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
に追加のロック (セマフォ) を追加することはできますが、このパフォーマンスへの影響を回避しようとします。CompleteAdding
Dispose
例外なくアイテムを追加するにはどうすればよいですか? アイテムの紛失は、追加が完了していれば問題ありません。