Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 告诉并发队列是否在不循环的情况下更新_C#_Multithreading_Concurrency - Fatal编程技术网

C# 告诉并发队列是否在不循环的情况下更新

C# 告诉并发队列是否在不循环的情况下更新,c#,multithreading,concurrency,C#,Multithreading,Concurrency,谢谢你的帮助。我有一个三线程进程,由一个并发队列链接。线程一处理信息,返回到第二个线程,第二个线程将数据放入并发队列。第三个线程就是这样循环的: while (true) { if(queue.TryDequeue(out info)) { doStuff(info); } else { Thread.Sleep(1); } } 有没有更好的方法来处理它,这样我就不会对循环进行太多的迭代?应用程序对性能非常敏感,目前只有TryDequeu

谢谢你的帮助。我有一个三线程进程,由一个并发队列链接。线程一处理信息,返回到第二个线程,第二个线程将数据放入并发队列。第三个线程就是这样循环的:

while (true) {
    if(queue.TryDequeue(out info)) {
        doStuff(info);
    } else {
        Thread.Sleep(1);
    }
}

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

你可以增加睡眠时间。我也会使用
等待任务。延迟
而不是睡眠。通过这种方式,您可以等待更长的时间,而不必使用
Thread.Sleep
使用的额外cpu周期,并且仍然可以通过使用
CancellationTokenSource
来取消延迟

另一方面,还有更好的工作排队方式。考虑到您似乎希望同步运行这些作业,例如使用一个singleton类来获取您的工作项并将其排队。因此,如果在添加项目时队列中没有项目,它应该检测到该项目,然后启动作业流程。在作业流程结束时,检查是否有更多的工作,使用递归来完成该工作,或者如果没有更多的作业,则退出作业流程,在向空队列添加项目时,作业流程将再次运行。如果我的假设是错误的,您可以并行运行这些作业,为什么要使用队列


您可能希望使用
ObservableCollection
的线程安全实现。检查这个问题,

你应该考虑使用Stase.Copys.CulcTurn.BulcCuin集合及其Add()/Author()方法。使用Take()时,您的第三个线程将在等待新项目时暂停。Add()是线程安全的,可由第二个线程使用

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

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

我没有一个可以避免循环的建议,但是我建议你远离循环

while (true)

并考虑这一点:

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

将它放在一个每次修改队列时都会调用的方法中,这样可以确保它在需要时运行,但在不需要时结束。

或使用
GetConsumingEnumerable
我以前使用过BlockingCollection,但发现我在*.take()中花费的时间比while(true)循环更多。不确定编程上的差异,但切换到ConcurrentQueue似乎显示了性能提升。我将调回,看看是否可以再次确认/否认您是如何测量时间的?在执行操作之前,我保存了Environment.TickCount,之后我将从保存的TickCount中减去它,并将其添加到计数器中ok。。如果你不在乎物品的顺序,你还可以尝试ConcurrentBag。这似乎会剥夺OP想要的东西。如果
TryDequeue
为false,则此代码将退出,因此无法继续检查新作业。我有点不愿意这样做,因为我必须确保此doWork()永远不会备份。我担心在有工作要做的时候产生一个新任务可能会导致任务创建和激活之间的延迟,这对于流程来说是完全不可接受的。Jacob,如果TryDequeue为false,那么就没有什么可以做的了,这就是为什么我声明在添加任何内容时必须再次调用循环方法的原因。一旦这个过程开始,假设有多个项目排队,那么它将继续“直到完成”。与上面的答案相同,出于性能原因,我需要所有这些都异步运行。应用程序现在每秒处理超过100k rabbitmq消息(峰值~138k/s),同步运行会破坏速度。我担心,如果我等到将数据放入队列后才生成一个处理线程,那么我将得到备份,因为任务创建和任务实际启动之间即使有几毫秒的延迟,也会造成灾难性的后果。这就是为什么我现在有一个全职运行的专用任务为什么还要使用队列,让第二个任务调用直接进入第三个任务?我已经异步运行了多个第一个任务,并且必须保持顺序,所以我不能让它们在完成下一个任务时启动。当前设置是一个任务队列,因此它们异步运行,我只需弹出顶部任务,等待它完成,获取结果并将其传递给下一个任务。这都是基于RabbitMQ消息的,第一个任务之一是在接收消息时产生并开始处理它。我已经完成了3个同时运行的进程任务,这是处理过程中实际工作量的大部分,看来您应该考虑重新编写工作流。您担心任务启动的顺序,但是如果您将任务添加到线程池,那么线程池将负责确定下一步应该运行哪个任务。这并不保证任何类型的订单。在不了解您的整个工作流程的情况下,我恐怕无法对您的执行计划提供太多帮助。也许考虑引发事件来触发下一步…同样,这只是我在混乱中推测一个特定的顺序。所以我确保顺序的方法是任务队列。当生成任务时(当消息传入并导致生成任务时),任务被放入队列中。任务本身不会影响外部数据,因此它们实际完成的顺序无关紧要。为了确保正确的顺序,我需要做的就是从队列中弹出最上面的任务,必要时调用task.wait(),然后获取结果。以这种方式设置它允许处理的并行化,同时保持输出的顺序