并行处理队列

时间:2012-07-04 12:02:39

标签: c# .net parallel-processing queue chaining

我有一个处理消息的类:

public abstract class ProcessingBase {
    public bool IsBusy { get; set; }
    public Queue<CustomMessage> PendingMessages { get; private set; }
    public abstract MessageProcessingResult Process();
    ...

在我迄今为止创建的处理模块中,使用队列处理消息,通过套接字发送消息,另一个发送电子邮件。这适用于单个处理模块,但假设我想链接这两个?

我以为我可以这样做:

public class ChainProcessor : ProcessingBase {
    public List<ProcessingBase> Processors { get; set; }
    public override MessageProcessingResult Process() {
                if (IsBusy)
                    return null;
                IsBusy = true;

                CustomMessage msg = null;
                this.ProcessedMessages = new List<CustomMessage>();

                // create clone of queue 
                var messagesToSend = new Queue<CustomMessage>(this.PendingMessages);
                this.PendingMessages.Clear();
                while (messagesToSend.Count > 0 && (msg = messagesToSend.Dequeue()) != null) {
                    foreach (var processor in this.Processors) {
                        // something with yield return?
                    }
                }

这是我摇摇欲坠的实际链接。理想情况下,我想用一种“波浪”来处理它们。例如:

Module 1 - Processed message A
Module 2 - Processed message A
Module 1 - Processed message B
Module 2 - Processed message B
Module 3 - Processed message A
Module 1 - Processed message C

每条消息都通过链传递,消息随着消息的不断进入和离开。这样做的最佳方式是什么?或者我是否仅限于将每条消息顺序传递到整个链中?

是的(我不想要的):     第1单元 - 已处理的消息A.     第2单元 - 已处理的消息A.     第3单元 - 已处理的消息A.     第1单元 - 已处理的消息B.     第2单元 - 已处理的消息B.     第3单元 - 已处理的消息B.     第1单元 - 已处理的消息C

编辑:我希望我可以做一些事情,第一个处理器将返回到'链处理器',这会将该消息传递到模块2,然后链可能启动处理器1上的下一条消息

2 个答案:

答案 0 :(得分:0)

我认为你可以使用

   BlockingCollection<CustomMessage>

每个模块。然后,您可以创建多个线程以从每个colelction读取并执行模块的处理工作。之后将其放入下一个模块的队列中。

通过创建多个线程,您可以并行工作。 BlockingCollection是线程安全的,快速的和阻塞的。很方便。见http://msdn.microsoft.com/en-us/library/dd267312.aspx

答案 1 :(得分:0)

您正在寻找线程安全ConcurrentQueueAutoResetEvent,女巫可以唤醒睡眠线程(参见示例)。

每个worker都在自己的线程上运行(如果你有一些主线程的工作),在它完成工作并清空其输入队列之后,调用AutoResetEvent.WaitOne()。如果某个项填充了输入队列,请调用AutoResetEvent.Set(),再次启动该过程。

您可以通过使用第一个工作程序处理的项创建第二个队列来链接这两个工作程序。在第一个worker完成消息后,将item添加到输出队列并调用AutoResetEvent.Set()

阅读并三思而后行,我不了解您的情况,因此您可以根据需要优化流程。

祝你好运。 ; - )