10 秒内不再重试的 BlockingCollection

BlockingCollection that doesn't try again within 10 seconds

我正在使用Blockingcollection作为FIFO queue但是我对文件做了很多操作,其中consumer可能很容易遇到文件锁定,所以我有done 创建了一个简单的 try catch,其中消费者重新排队,但是在队列中有很多其他项目的长 FIFO queue 中,这足以暂停,但在空的或非常短的 FIFO queue 这意味着 consumer 不断地通过自身重复出现来敲击队列,这些事件可能仍会被文件锁定。

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

有没有办法让 BlockingCollection 不尝试 运行 新消费者,如果它不到 10 秒?也就是说,如果 createdDateTime 为 null(第一次尝试的默认值)或者大于 10 秒,则可能会在队列中获得净值并继续,并且只接受下一个消费者?

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

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

您可以保留两个阻塞集合:主要集合和 "delayed" 集合。一个工作线程只会在延迟的线程上工作,将它们读到主集合中。被拒绝集合的签名类似于:

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);
        }
    }
}