多线程.NET队列问题 [英] Multithreaded .NET queue problems

查看:133
本文介绍了多线程.NET队列问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有我的code一个奇怪的错误。这是非常罕见的(发生每隔几个星期一次也许),但它的存在,我不知道为什么。

我们有2个线程中运行,1线程获取网络信息,并将它们添加到队列是这样的:

  DataMessages.Enqueue(新的DataMessage(客户端,味精));
 

另一个线程需要关闭的消息队列和处理它们,像这样的:

 而(NetworkingClient.DataMessages.Count大于0)
{
    的DataMessage消息= NetworkingClient.DataMessages.Dequeue();

    开关(message.messageType)
    {
       ...
    }
}
 

然而,一旦每隔一段时间我上线一个NullReferenceException 开关(message.messageType),我可以在该消息为空调试器看到的。

这是不可能的,一个空值被放到队列(见code中的第一位),而这些是仅有的两件事情使用该队列。

时的队列不是线程安全的,会不会是我在出队,其他线程入队的准确时间,这将导致该故障?

解决方案

 而(NetworkingClient.DataMessages.Count大于0)
    {
        //每两周一次上下文切换恰好是在这里。
        的DataMessage消息= NetworkingClient.DataMessages.Dequeue();

        开关(message.messageType)
        {
           ...
        }
    }
 

...当你在那个位置上下文切换中,第一八佰伴pression结果 ( NetworkingClient.DataMessages.Count> 0 )是适用于两个线程,以及一个获得的对出列()操作首先得到的对象,第二个线程获取是一个空(而不是InvalidOperationException异常,因为队列的内部状态并没有完全更新抛出的权利除外)。

现在你有两个选择:

  1. 使用了.NET 4.0 ConcurrentQueue

  2. 重构你的code:

和使它看起来在某种程度上是这样的:

 ,而(真)
{
  的DataMessage消息= NULL;

  锁定(NetworkingClient.DataMessages.SyncRoot){
       如果(NetworkingClient.DataMessages.Count大于0){
          消息= NetworkingClient.DataMessages.Dequeue();
       } 其他 {
         打破;
       }
    }
    你的code // ..休息
}
 

编辑:更新,以反映Heandel的评论。

I'm have a wierd error in my code. It's extremely rare (happens once every few weeks maybe), but it's there and I'm not sure why.

We have 2 threads running, 1 thread gets networked messages and adds them to a Queue like this:

DataMessages.Enqueue(new DataMessage(client, msg));

Another thread takes messages off this queue and handles them, like this:

while (NetworkingClient.DataMessages.Count > 0)
{
    DataMessage message = NetworkingClient.DataMessages.Dequeue();

    switch (message.messageType)
    {
       ...
    }
}

However once every so often I get a NullReferenceException on the line switch (message.messageType) and I can see in the debugger that message is null.

It is not possible that a null value was put onto the queue (see the first bit of code), and these are the only 2 things that use the queue.

Is Queue not thread-safe, could it be that I'm dequeuing at the exact moment that the other thread is enqueuing and this causes the glitch?

解决方案

    while (NetworkingClient.DataMessages.Count > 0)
    {
        // once every two weeks a context switch happens to be here.
        DataMessage message = NetworkingClient.DataMessages.Dequeue();

        switch (message.messageType)
        {
           ...
        }
    }

... and when you get that context switch in that location, the result of the first expression (NetworkingClient.DataMessages.Count > 0) is true for both threads, and the one that get's to the Dequeue() operation first get's the object and the second thread get's a null (instead of InvalidOperationException because the Queue's internal state wasn't fully updated to throw the right exception).

Now you have two options:

  1. Use the .NET 4.0 ConcurrentQueue

  2. Refactor your code:

and make it look somehow like this:

while(true)
{
  DataMessage message = null;

  lock(NetworkingClient.DataMessages.SyncRoot) {
       if(NetworkingClient.DataMessages.Count > 0) {
          message = NetworkingClient.DataMessages.Dequeue();
       } else {
         break;
       }
    }
    // .. rest of your code
}

Edit: updated to reflect Heandel's comment.

这篇关于多线程.NET队列问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆