Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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_Queue - Fatal编程技术网

为什么在C#中,队列会扰乱其元素中的数据?

为什么在C#中,队列会扰乱其元素中的数据?,c#,multithreading,queue,C#,Multithreading,Queue,我对队列的功能完全感到困惑。我正在尝试(但未能)写作 一个小型多线程应用程序,用于在C#中收集和显示数据。 在通读并使用消费者/生产者 他描述的模式是,除了我的数据在未来似乎被打乱之外,我的大部分数据都能正常工作 队列在排队之前,我的对象中的字段具有以下值 时间戳=6 数据[]={493698452412544861} 在退出队列后,数据看起来像 时间戳=6 数据[]={6479119464777265405} 我不明白为什么数据字段中的值在出列后被更改? 我很困惑,所以我想我会把它扔出去,看看

我对队列的功能完全感到困惑。我正在尝试(但未能)写作 一个小型多线程应用程序,用于在C#中收集和显示数据。
在通读并使用消费者/生产者 他描述的模式是,除了我的数据在未来似乎被打乱之外,我的大部分数据都能正常工作 队列在排队之前,我的对象中的字段具有以下值

时间戳=6
数据[]={493698452412544861}

在退出队列后,数据看起来像

时间戳=6
数据[]={6479119464777265405}

我不明白为什么数据字段中的值在出列后被更改? 我很困惑,所以我想我会把它扔出去,看看是否有人能给我指出正确的方向来解决这个问题,或者给我指出一个不同的方向来继续


相关代码


用于数据存储的自定义对象

相关对象和字段。sensorData类是一个单独的类,用于存储我的计算

public class sensorData
{
    public const int bufSize = 4;
    public UInt16[] data = new UInt16[4];
    public double TimeStamp = 0; 
    public int timeIndex = 0;
}
以下字段用于设置队列以及入队列和出队列线程之间的信号

EventWaitHandle wh = new AutoResetEvent(false);
Queue<sensorData> dataQ = new Queue<sensorData>();
object locker = new object();
将数据排入队列并将其写入DequeueDataTest.txt

6479119464777265405


更新1:

当前代码中锁的位置。


我已经编辑了代码,以便在将数据写入文件时锁定。所以我有锁的代码块如下

在CalculateAndEnqueueData()方法中

lock (locker) dataQ.Enqueue(dat);
wh.Set

lock(locker)
{
  sw2.Write(j.ToString() + ", ");
  foreach (UInt16 dd in dat.intData)
  {
     sw2.Write(dd.ToString() + ", ");
  }
  sw2.WriteLine();
}
在dequeueDataMethod()中,我有两个带锁的区域,第一个在这里

lock(locker) 
    if (dataQ.Count > 0)
    {
       data = dataQ.Dequeue();
       if (data == null)
       {
           sw.Close();
           return;
        }
    }
我假设它为if块中的代码锁定锁。第二个是我在这里写入文件的地方

lock (locker)
{
    sw.Write(data.timeIndex.ToString() + ", ");
    foreach (UInt16 dd in data.intData)
        sw.Write(dd.ToString() + ", ");
    sw.WriteLine();
    if (icnt > 10)
    {
        sw.Close();
        return;
    }
    this.label1.Text = dataQ.Count.ToString();
}
就这些



问题是由于您正在写入的StreamWriter没有同步。顺序不是连续的。

是不是因为您在一次又一次地向同一个数组写入
UInt16[]intDist
?您不应该为每个
sensorData
对象使用单独的数组吗?(顺便说一句,在示例代码中是
sensorData.intData
假设是
sensorData.data

澄清:

CalculateAndQueueData()
中只创建了一个
intDist
数组,因此不同的
sensorData
实例都共享同一个数组---如果在锁定步骤中发生添加+写入和删除+写入,则这是正常的;否则,某些数据点可能丢失/重复

建议:

直接填充
sensorData
实例,而不使用
intDist
数组,在
calculateAndEnqueueData()中

//创建新的sensorData实例
sensorData dat=新的sensorData();
dat.TimeStamp=时间;
dat.timeIndex=j;
//计算四条正弦曲线
对于(int i=0;i
当然,您可以让代码变得越来越简单,并且仍然可以演示您看到的问题。您正在锁定队列,但是StreamWriter上的同步在哪里???每个线程都写入一个单独的文件。因此,我认为我不需要对线程的这一部分进行同步。我错了吗?在dequeueDataMethod()中方法,我只看到一个文件。是的,dequeueDataMethod写入test.txt,CalculateAndQueueData写入test2.txt。是的,我需要在写入文件的代码周围放置一个锁。谢谢。这正是我所需要的!我以为你说每个线程都在写入一个单独的文件?我不认为StreamWriter的同步,这是的,每个线程都会写入不同的文件(test.txt和test2.txt)。我所知道的是,锁定代码块周围的锁似乎有帮助。我不知道为什么。这似乎只起作用,因为intDist是“作为块”写入和读取的…但是我认为这仍然是不正确的。要了解这一点,请在CalculateAndQueueData()中放置2秒延迟,在dequeueDataMethod()中放置4秒延迟然后看看会发生什么。@Zach Scrivena:好的,按照你的建议添加了延迟。代码似乎有效。我让它运行了大约1分钟,它的行为很好。两个文件都是相同的。是的,谢谢。我的代码被删减了。最初,sensorData有几个字段被使用,我在这个问题中删除了。不,我不这么认为,因为e生产者线程CalculateAndQueueData写入UInt16[]生成正确的数据。数据在消费者线程DequeueDataMethod中出列时被置乱,这是因为它们被“作为块”写入……出列时,相同的数组被修改(尽管对于不同的sensorData对象)通过计算DenQueueData,从而得出错误的结果。似乎您的代码是在锁定步骤中写入和读取sensorData对象——这就是目的吗?(检查队列长度是否超过一个……我怀疑没有)。是的,如果我减慢出队速度,队列长度将增加。因此队列长度可以增加到一个以上。
lock(locker) 
    if (dataQ.Count > 0)
    {
       data = dataQ.Dequeue();
       if (data == null)
       {
           sw.Close();
           return;
        }
    }
lock (locker)
{
    sw.Write(data.timeIndex.ToString() + ", ");
    foreach (UInt16 dd in data.intData)
        sw.Write(dd.ToString() + ", ");
    sw.WriteLine();
    if (icnt > 10)
    {
        sw.Close();
        return;
    }
    this.label1.Text = dataQ.Count.ToString();
}
    // create new sensorData instance
    sensorData dat = new sensorData();
    dat.TimeStamp = time;
    dat.timeIndex = j;

    // Calculate four Sine curves
    for (int i = 0; i < collectedData.numberOfChannels; i++)
    {
        dat.data[i] = (UInt16) Math.Abs(Math.Sin(2.0 * Math.PI * myFrequency[i] * time);
    }

    // enqueue
    lock (locker) dataQ.Enqueue(dat);