C# 队列上的竞争条件

C# 队列上的竞争条件,c#,.net,multithreading,c#-4.0,race-condition,C#,.net,Multithreading,C# 4.0,Race Condition,下面的代码处理带有2个参数的套接字消息。它将信息放入队列并在另一个线程上处理。我的问题是,如果两条消息紧跟在另一条消息之后进入队列并发送到方法ProcessData,ProcessData上是否存在竞争条件 private void DataIn(long Code, string Message) { if (!Started) { if (DataInQueue == null) DataInQueue = new Queue(); DataInThrea

下面的代码处理带有2个参数的套接字消息。它将信息放入队列并在另一个线程上处理。我的问题是,如果两条消息紧跟在另一条消息之后进入队列并发送到方法ProcessData,ProcessData上是否存在竞争条件

private void DataIn(long Code, string Message)
{
  if (!Started)
  {
    if (DataInQueue == null)
      DataInQueue = new Queue();
    DataInThread = new Thread(new ThreadStart(ThreadProcedure));
    DataInThreadEnding = false;
    DataInThread.IsBackground = true;
    DataInThread.Start();
    Started = true;
  }
  DataInQueue.Enqueue(new cDataIn(Code, Message));
}

private void ThreadProcedure()
{
   while (!ProgramEnding)
   {
     Queue mySyncdQ = Queue.Synchronized(DataInQueue);
     if (mySyncdQ != null && mySyncdQ.Count > 0)
     {
        cDataIn data = null;
        // Creates a synchronized wrapper around the Queue. 
        if (mySyncdQ.Count > 0)
          data = (cDataIn)mySyncdQ.Dequeue();

        ProcessData(data);
    }
  }

}
更新

在您的代码中,队列未以线程安全的方式使用。。。您显示的代码不足以确定是否存在竞争条件,但使用
ConcurrentQueue
您可以获得更好的性能。。。在ThreadProcedure中,您可以使用null调用ProcessData,就我所知,为了安全起见,ProcessData应该是可重入的,所有这些都可以工作

使用-可以避免一些可能的问题。。。并查看为线程安全生产者/消费者场景设计的。。。这两种方法都可以无锁工作,而且速度非常快

更新

在您的代码中,队列未以线程安全的方式使用。。。您显示的代码不足以确定是否存在竞争条件,但使用
ConcurrentQueue
您可以获得更好的性能。。。在ThreadProcedure中,您可以使用null调用ProcessData,就我所知,为了安全起见,ProcessData应该是可重入的,所有这些都可以工作


使用-可以避免一些可能的问题。。。并查看为线程安全生产者/消费者场景设计的。。。这两种方法都可以无锁工作,而且速度非常快

是的,我认为这甚至会使您的队列处于不稳定状态。您应该使用.NET4附带的。它的线程安全的开箱即用和优化


向Gert Jan致意

是的,我认为这甚至会使您的队列处于不稳定状态。您应该使用.NET4附带的。它的线程安全的开箱即用和优化


关于Gert Jan,您的代码不是线程安全的。请注意:

为了保证
队列的线程安全
,所有操作必须仅通过此包装器完成

您直接使用队列,因此代码不是线程安全的。要解决此问题,请始终使用返回的包装器,如文档所述

或者,如果您在.Net 4下,请使用
ConcurrentQueue


如果您想在早期版本的.Net上使用通用队列,您可以使用
队列
,并始终在
锁中访问它

您的代码不是线程安全的。请注意:

为了保证
队列的线程安全
,所有操作必须仅通过此包装器完成

您直接使用队列,因此代码不是线程安全的。要解决此问题,请始终使用返回的包装器,如文档所述

或者,如果您在.Net 4下,请使用
ConcurrentQueue



如果您想在早期版本的.Net上使用通用队列,您可以使用
队列
,并始终在
锁中访问它

您是说有问题吗?队列类的文档()底部有一段关于线程安全的内容,说明实例成员不是TS。我还没有查看实现,看看会发生什么,但是您可以通过旋转两个线程来检查自己。一个泵入顺序消息(1,2,3,…),另一个读取它们。您可能会得到一个异常或间隙/双精度(1,2,2,4,5,…)+1对于BlockingCollection,这是jon描述的P-C场景中使用的类。您是说有问题吗?队列类的文档()底部有一段关于线程安全的内容,说明实例成员不是TS。我还没有查看实现,看看会发生什么,但是您可以通过旋转两个线程来检查自己。一个泵入顺序消息(1,2,3,…),另一个读取它们。您可能会得到一个异常或间隙/双精度(1,2,2,4,5,…)+1对于BlockingCollection,这是在jon描述的P-C场景中使用的类。您为什么说队列有问题?我更担心ProcessData会很快被连续调用,第二个线程可能会超过第二个线程first@Jon,内存泄漏很可能不会影响你。你可以自己做一个测试台,就像我在Yahia的回答中建议的那样。这取决于队列的内部实现。它可能会在引擎盖下使用一个需要复制的数组,当您同时复制两次时,可能会使其处于不满意的状态。我不会;Don’别冒这个险1.你为什么说排队有问题?我更担心ProcessData会很快被连续调用,第二个线程可能会超过第二个线程first@Jon,内存泄漏很可能不会影响你。你可以自己做一个测试台,就像我在Yahia的回答中建议的那样。这取决于队列的内部实现。它可能会在引擎盖下使用一个需要复制的数组,当您同时复制两次时,可能会使其处于不满意的状态。我不会;不要冒险..所以我需要在排队和退队时调用synchronize?这就是文档中所说的,不是吗?实际上没有说排队和退队Genqueue和退队是操作,所以它确实是这样说的。所以我需要在排队和退队时调用synchronize?这就是文档中所说的,不是吗?实际上并没有说排队和退队排队和退队都是操作,所以它确实是这样说的。