如何在没有竞争条件和异常的情况下检测BlockingCollection的AddingCompleted?

时间:2014-07-01 06:44:12

标签: 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);
    }
}

是的我知道这段代码没有意义,因为几乎没有机会添加任何项目,而foreach-loop注意到了。消耗任务对我的问题无关紧要。

问题显示在ConsumeItem - 方法中。我可以添加一个额外的锁(信号量)arround ConsumeItemCompleteAdding + Dispose,但我尽量避免这种性能影响。

如何添加项目,没有任何例外?如果添加完成,丢失的项目将会很好。

0 个答案:

没有答案