告诉并发队列是否在没有循环的情况下更新

本文关键字:循环 情况下 更新 并发 队列 是否 | 更新日期: 2023-09-27 18:06:50

感谢您的协助。我有一个三线程进程,由并发队列连接。线程1处理信息,返回到第二个线程,第二个线程将数据放入并发队列。第三个线程就像这样循环:
while (true) {
    if(queue.TryDequeue(out info)) {
        doStuff(info);
    } else {
        Thread.Sleep(1);
    }
}

是否有更好的方法来处理它,这样我就不会在循环中迭代这么多?该应用程序对性能非常敏感,目前仅TryDequeue就占用了应用程序运行时的8-9%。希望尽可能地减少,但不确定我有什么选择

告诉并发队列是否在没有循环的情况下更新

你应该考虑使用System.Collections.Concurrent.BlockingCollection及其Add()/Take()方法。使用Take()时,第三个线程将在等待新项目时暂停。Add()是线程安全的,可以被第二个线程使用。

使用这种方法,您应该能够将代码简化为如下内容:

while (true) {
   var info = collection.Take();
   doStuff(info);
}

可以增加睡眠时间。我也会用await Task.Delay代替睡眠。这样,您可以等待更长的时间,而不需要Thread.Sleep使用额外的cpu周期,并且仍然能够通过使用CancellationTokenSource来取消延迟。

另一方面,有更好的方法来排队作业。考虑到您似乎想要同步运行这些作业,一个例子是有一个单例类,它接受您的工作项并将它们排队。因此,当您添加一个项目时,如果队列中没有项目,它应该检测到这一点,然后启动您的作业进程。在作业进程结束时,检查是否有更多的工作,使用递归来完成该工作,或者如果没有更多的作业,则退出作业进程,当向空队列添加一个项目时,该进程将再次运行。如果我的假设是错误的,并且您可以并行运行这些作业,那么为什么要使用队列呢?

您可能希望使用ObservableCollection的线程安全实现。查看这个SO问题ObservableCollection和threading

我不建议避免循环,但是我建议您不要使用

while (true)

,考虑下面这个:

MyThing thing;
while (queue.TryDequeue(out thing))
{
    doWork(thing);
}

将其放在每次修改队列时调用的方法中,这确保它在需要时运行,但在不需要时结束。