Seb*_*ann 6 c# multithreading race-condition blockingcollection
我使用的BlockingCollection{T}是仅由一个线程填充且仅由一个线程消耗的线程。生产和消费物品运行良好。问题出在这个操作的最后。任务在 处阻塞(如预期)GetConsumingEnumerable。CompleteAdding调用任务后将处理BlockingCollection并完成,没有任何异常。到目前为止,一切都很好。
现在我有一个线程将项目添加到BlockingCollection. 该线程必须进行测试IsAddingCompleted,然后必须添加该项目。IsAddingCompleted但请求和添加项目之间存在竞争条件。有一个TryAdd- 方法,但如果添加已经完成,也会引发异常。
如何在没有额外锁定的情况下添加已完成的项目或测试?为什么会TryAdd抛出异常?如果添加已经完成,返回false即可。
非常简化的代码如下所示:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
是的,我知道这段代码没有意义,因为几乎没有机会添加任何项目,并且 foreach 循环没有注意到。消耗任务对我的问题来说并不重要。
问题如ConsumeItem-method 所示。我可以添加一个额外的锁(信号量)ConsumeItem和CompleteAdding+ Dispose,但我试图避免这种性能影响。
如何添加项目而不出现任何异常?如果添加完成,丢失物品也没关系。