当集合为空时,BlockingCollection TryTake返回false而不是block

时间:2018-05-23 08:51:29

标签: c# task-parallel-library blockingcollection

BlockingCollection 为空时,我从BlockingCollection的 TryTake 方法返回false,尽管预期的行为是阻塞,直到集合填满为止。

请注意,集合不是上限(这应该影响TryAdd而不是TryTake),并且没有为add操作设置超时。

这是我在BlockingCollection对象周围的包装器:

    public T TryTake(int timeoutMiliseconds)
    {
        var result = default(T);

        if (!_collection.TryTake(out result, timeoutMiliseconds))
        {
            throw new InvalidOperationException("Unable to get item from collection.");
        }

        return result;
    }

任何可能导致这种情况的想法?

我已经基于这篇文章实现了Producer-Consumer模式: Multithread processing of the SqlDataReader - Producer/Consumer design pattern

1 个答案:

答案 0 :(得分:0)

我终于意识到,正如SO post所示,我从TryTake中弄错了因为集合已被清空,并且我也标记为已完成(通过调用CompleteAdding()方法集合)。

因此,为了解决这个问题,我在已完成的旗帜上添加了条件。

有人可能会说TryTake永远不会返回 false ,而已完成的标记 false 。我不确定它总是正确的,所以我更倾向于在这种情况下抛出错误。

    public T TryTake(int timeoutMiliseconds)
    {
        var result = default(T);

        if (!_collection.TryTake(out result, timeoutMiliseconds) 
            && !_collection.IsAddingCompleted)
        {
            throw new InvalidOperationException("Unable to get item from collection.");
        }

        return result;
    }

请注意,首先TryTake调用和IsAddingCompleted秒调用至关重要。否则,第一个条件可能会过去,您将在TryTake之后立即阻止。