2

我正在使用 a Blockingcollectionas aFIFO queue但我正在对文件进行很多操作,其中consumer可能很容易遇到文件锁,所以我所做的是创建一个简单的 try catch,其中消费者重新排队本身,但在很长一段时间FIFO queue内队列中的许多其他项目,这足以暂停,但在一个空的或非常短的情况下FIFO queue,这意味着consumer永久地锤击队列,重复出现可能仍将被文件锁定的自身。

IE

consumer busy-> 重新排队 -> consumer busy -> 重新排队(无限期)

BlockingCollection如果新消费者不到 10 秒,有没有办法让它不尝试运行它?即可能在队列中获取网络并继续,如果它的 createdDateTime 为空(第一次尝试的默认值)或> 10秒,则只接受下一个消费者?

4

2 回答 2

3

没有任何内置的帮助。与每个工作项一起存储DateTime上次尝试的时间(null如果这是第一次尝试,则可能是)。然后,在您的处理功能中等待TimeSpan.FromSeconds(10) - (DateTime.UtcNow - lastAttemptDateTime)几秒钟,然后再进行下一次尝试。

考虑切换到优先级队列,该队列按照最早下一次尝试日期时间的顺序存储项目。

于 2015-05-18T12:25:46.310 回答
2

您可以保留两个阻塞集合:主集合和“延迟”集合。一个工作线程只能处理延迟的线程,将它们读入主集合。被拒绝集合的签名将类似于:

BlockingCollection<Tuple<DateTime, YourObject>>

现在......如果时间固定在 10 秒,延迟的集合将几乎被DateTime排序(如果项目几乎同时添加,这可能不是真的,但我们说的是毫秒差异......不是问题)

public class MainClass
{
    // The "main" BlockingCollection
    // (the one you are already using)
    BlockingCollection<Work> Works = new BlockingCollection<Work>();

    // The "delayed" BlockingCollection
    BlockingCollection<Tuple<DateTime, Work>> Delayed = new BlockingCollection<Tuple<DateTime, Work>>();

    // This is a single worker that will work on the Delayed collection
    // in a separate thread
    public void DelayedWorker()
    {
        Tuple<DateTime, Work> tuple;

        while (Delayed.TryTake(out tuple, -1))
        {
            var dt = DateTime.Now;

            if (tuple.Item1 > dt)
            {
                Thread.Sleep(tuple.Item1 - dt);
            }

            Works.Add(tuple.Item2);
        }
    }
}
于 2015-05-18T12:58:35.807 回答