Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/319.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# .NET BlockingCollection除一个线程外,所有线程都处理消息_C#_.net_Multithreading_Blockingcollection - Fatal编程技术网

C# .NET BlockingCollection除一个线程外,所有线程都处理消息

C# .NET BlockingCollection除一个线程外,所有线程都处理消息,c#,.net,multithreading,blockingcollection,C#,.net,Multithreading,Blockingcollection,我有一个使用阻塞集合的类: public class MessageQueue : IDisposable { private BlockingCollection<Message> queue; private MessageHandler messageHandler; private CancellationToken cancellationToken; public MessageQueue(MessageHandler handler,

我有一个使用阻塞集合的类:

public class MessageQueue : IDisposable
{
    private BlockingCollection<Message> queue;
    private MessageHandler messageHandler;
    private CancellationToken cancellationToken; 

    public MessageQueue(MessageHandler handler, CancellationToken cancellationToken)
    {
        this.messageHandler = handler;
        this.cancellationToken = (cancellationToken != null) ? cancellationToken : new CancellationToken();

        for (int i = 0; i < Environment.ProcessorCount; i++)
        {
            Task.Factory.StartNew(() => DequeueMessage());
        }
    }

    public void Enqueue(Message message)
    {
        queue.Add(message);
    }

    private void DequeueMessage()
    {
        Message message;

        while (!cancellationToken.IsCancellationRequested)
        {
            if (queue.TryTake(out message, 5000, cancellationToken))
            {
                messageHandler.Handle(message);
            }
        }
    }
}
公共类消息队列:IDisposable
{
私有阻塞收集队列;
私有MessageHandler MessageHandler;
私有取消令牌取消令牌;
公共消息队列(MessageHandler处理程序,CancellationToken CancellationToken)
{
this.messageHandler=handler;
this.cancellationToken=(cancellationToken!=null)?cancellationToken:new cancellationToken();
for(int i=0;iDequeueMessage());
}
}
公共无效排队(消息)
{
添加(消息);
}
私有void出列消息()
{
信息;
而(!cancellationToken.IsCancellationRequested)
{
if(queue.TryTake(out消息,5000,cancellationToken))
{
Handle(message);
}
}
}
}

只要所有使用者线程正确地启动消息出列,消息被排队,并且所有线程都将其第一条消息从队列中取出并开始处理,那么所有线程都看起来不错。但是,在此之后,只有一个线程继续处理消息。所有其他线程似乎都转到线程池去做其他事情。我在dequeue方法中有一个日志,它将记录一个退出该方法的线程——没有一个线程记录它。我没想到会这样,我很困惑。有没有一个很好的解释来解释我不理解的这种行为

messageHandler
是否会引发异常?如果它这样做了,那么它将停止该线程上的执行。还有,你的消息处理程序和日志记录方法是线程安全的吗?哦,糟了,没错,斯科特!非常感谢…在我的日志中没有看到任何错误,所以假设一切都很好。但是在try/catch now中包装对Handle(message)的调用会显示System.Collections.ListDictionaryInternal Hmmm…现在需要弄清楚这是怎么回事:-)您应该在
DequeueMessage
中使用,而不是现在这样做。Matthew,我已经尝试过了,也遇到了同样的问题。或者你是说GetConsumingEnumerable()比TryTake()更好?是的,
GetConsumingEnumerable()
是推荐的方法。