C# 生产者/消费者按队列获取不同的数据
解决了!!!谢谢 当心你把什么样的对象放入队列中。如果你放入一个值,比如int,那么队列将生成一个副本,每个人都很高兴。若你们把一个引用,比如byte[],string,enqueue,把这个引用放到队列中,那个么问题就来了。如果在使用者读取此参考之前更改了此参考,则使用者将读取已更改的数据版本 为了避免这个问题,在进入队列后立即在rxThread中获取新版本的帧引用。代码:C# 生产者/消费者按队列获取不同的数据,c#,multithreading,queue,pass-by-reference,thread-priority,C#,Multithreading,Queue,Pass By Reference,Thread Priority,解决了!!!谢谢 当心你把什么样的对象放入队列中。如果你放入一个值,比如int,那么队列将生成一个副本,每个人都很高兴。若你们把一个引用,比如byte[],string,enqueue,把这个引用放到队列中,那个么问题就来了。如果在使用者读取此参考之前更改了此参考,则使用者将读取已更改的数据版本 为了避免这个问题,在进入队列后立即在rxThread中获取新版本的帧引用。代码: public void rxThreadFunc() { byte[] data =
public void rxThreadFunc()
{
byte[] data = new byte[datalen];//declare for the first iteration.
int j = 0;
while (true)
{
for (int i = 0; i < rxlen; i++)
{
data[j] = (byte)i;
j++;
if (j >= datalen)
{
j = 0;
mQ.Add(data);
using (StreamWriter fwriter = new StreamWriter("C:\\testsave\\rxdata", true))
{
for (int k = 0; k < datalen; k++)
{
fwriter.Write(data[k]);
fwriter.Write(",");
}
fwriter.Write("\n");
}
data = new byte[datalen];//create new reference after enqueue/Add
}
}
}
}//rxThreadFunc()
RxThread保存的rxData正确,显示:
2015/07/18 18:40:26.125,127,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,111,51,204,
2015/07/18 18:40:26.177,128,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,112,51,204,
2015/07/18 18:40:26.177,128,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,113,51,204,
2015/07/18 18:40:26.297,127,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,114,51,204,
2015/07/18 18:40:26.298,127,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,115,51,204,
2015/07/18 18:40:26.298,127,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,116,51,204,
2015/07/18 18:40:26.299,127,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,117,51,204,
2015/07/18 18:40:26.420,127,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,118,51,204,
//^this columns is accumulated number
dataProcessThread保存的dPdata错误,显示:
2015/07/18 18:40:31.904,127,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,227,51,204,
2015/07/18 18:40:31.905,127,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,228,51,204,
2015/07/18 18:40:31.905,127,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,229,51,204,
2015/07/18 18:40:32.026,128,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,51,204,
2015/07/18 18:40:32.026,128,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,51,204,
2015/07/18 18:40:32.147,128,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,232,51,204,
2015/07/18 18:40:32.148,128,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,233,51,204,
2015/07/18 18:40:32.148,128,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,234,51,204,
2015/07/18 18:40:32.269,128,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,236,51,204,
2015/07/18 18:40:32.269,128,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,236,51,204,
2015/07/18 18:40:32.510,128,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,237,51,204,
2015/07/18 18:40:32.512,128,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240,51,204,
2015/07/18 18:40:32.512,128,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240,51,204,
2015/07/18 18:40:32.514,127,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240,51,204,
2015/07/18 18:40:32.514,127,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,241,51,204,
2015/07/18 18:40:32.635,128,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,243,51,204,
2015/07/18 18:40:32.635,128,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,243,51,204,
//^this accumulated number is not correct
请帮忙
谢谢大家! FrameStruct是一个类(而不是一个结构),当您对它排队时,您会反复使用相同的引用 FrameStruct是一个类(而不是一个结构),当您对它排队时,您会反复使用相同的引用 更新2 这是基本的生产者消费者,只需添加您的逻辑:
class Program
{
static BlockingCollection<int> mQ = new BlockingCollection<int>();
static void Main(string[] args)
{
Thread rxThread = new Thread(rxThreadFunc);
rxThread.Priority = ThreadPriority.Highest;//this causes problem
rxThread.Start();
Thread procThread = new Thread(dataProc);
procThread.Start();
Console.ReadLine();
}
static public void rxThreadFunc()
{
for (int i = 0; i < 10; i++)
{
mQ.Add(i);
}
}
static public void dataProc()
{
foreach (int outData in mQ.GetConsumingEnumerable())
{
Console.WriteLine(outData);
}
}
}
如保存的数据文件所示:在损坏的文件中,每次缺少值(例如230)时,都会复制其他值(例如231)。缺失值的计数等于重复值的计数
原因是您将对同一对象实例的引用添加到队列中。
让我们看看下面的场景:RxThread循环N次,在它将上下文切换到dataProcess线程之前,它将N个引用添加到队列的FrameStruct的相同实例中。此实例中的数据将是上下文切换之前的上一次读取循环迭代中的数据。
现在,上下文切换发生了:dataProcess循环M答案很长:在dataProcess thread执行Monitor.Wait之后,它将进入等待队列,上下文开关将调度RxThread。现在,线程将第一个元素添加到队列并执行Monitor.Pulse。这会将dataProcess线程移动到就绪队列。但不一定安排它立即运行,所以RxThread可以进行另一次迭代。但是,如果您执行Thread.Sleep-很有可能会发生上下文切换,并且ataProcess线程现在将被调度。更新2 这是基本的生产者消费者,只需添加您的逻辑:
class Program
{
static BlockingCollection<int> mQ = new BlockingCollection<int>();
static void Main(string[] args)
{
Thread rxThread = new Thread(rxThreadFunc);
rxThread.Priority = ThreadPriority.Highest;//this causes problem
rxThread.Start();
Thread procThread = new Thread(dataProc);
procThread.Start();
Console.ReadLine();
}
static public void rxThreadFunc()
{
for (int i = 0; i < 10; i++)
{
mQ.Add(i);
}
}
static public void dataProc()
{
foreach (int outData in mQ.GetConsumingEnumerable())
{
Console.WriteLine(outData);
}
}
}
如保存的数据文件所示:在损坏的文件中,每次缺少值(例如230)时,都会复制其他值(例如231)。缺失值的计数等于重复值的计数
原因是您将对同一对象实例的引用添加到队列中。
让我们看看下面的场景:RxThread循环N次,在它将上下文切换到dataProcess线程之前,它将N个引用添加到队列的FrameStruct的相同实例中。此实例中的数据将是上下文切换之前的上一次读取循环迭代中的数据。
现在,上下文切换发生了:dataProcess循环M答案很长:在dataProcess thread执行Monitor.Wait之后,它将进入等待队列,上下文开关将调度RxThread。现在,线程将第一个元素添加到队列并执行Monitor.Pulse。这会将dataProcess线程移动到就绪队列。但不一定安排它立即运行,所以RxThread可以进行另一次迭代。但是如果您执行Thread.Sleep-很有可能会发生上下文切换,并且现在会安排ataProcess线程。您是否验证了问题是多线程的?你单独测试了每个部件吗?是的,我单独测试了。我将rawdata保存在rxThread中,它显示OK。但是dataProcess中的rawdata1不正常。这家伙可能有类似的问题,但他的问题没有得到回答。只是想弄清楚你想做什么:你想让作者在队列中有一个元素后立即完成他的工作吗?或者您可以允许队列具有多个元素?我可以允许队列具有多个元素。您是否验证了问题是多线程的?你单独测试了每个部件吗?是的,我单独测试了。我将rawdata保存在rxThread中,它显示OK。但是dataProcess中的rawdata1不正常。这家伙可能有类似的问题,但他的问题没有得到回答。只是想弄清楚你想做什么:你想让作者在队列中有一个元素后立即完成他的工作吗?或者您可以允许队列具有多个元素?我可以允许队列具有多个元素。谢谢,mate,但我尝试使用byte[]frame而不是FrameStruct作为队列的结构(queue messageQ=new queue,messageQ.Enqueue(frame)),它不起作用。实际上,一开始我将FrameStruct声明为Struct,但我看到一些人说在C#中使用class比使用Struct更好,所以我将其改为class。没关系,FrameStruct是引用类型,然后您必须在每个I中初始化一个新实例
2015/07/18 18:40:26.125,127,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,111,51,204,
2015/07/18 18:40:26.177,128,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,112,51,204,
2015/07/18 18:40:26.177,128,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,113,51,204,
2015/07/18 18:40:26.297,127,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,114,51,204,
2015/07/18 18:40:26.298,127,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,115,51,204,
2015/07/18 18:40:26.298,127,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,116,51,204,
2015/07/18 18:40:26.299,127,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,117,51,204,
2015/07/18 18:40:26.420,127,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,118,51,204,
//^this columns is accumulated number
2015/07/18 18:40:31.904,127,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,227,51,204,
2015/07/18 18:40:31.905,127,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,228,51,204,
2015/07/18 18:40:31.905,127,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,229,51,204,
2015/07/18 18:40:32.026,128,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,51,204,
2015/07/18 18:40:32.026,128,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,231,51,204,
2015/07/18 18:40:32.147,128,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,232,51,204,
2015/07/18 18:40:32.148,128,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,233,51,204,
2015/07/18 18:40:32.148,128,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,234,51,204,
2015/07/18 18:40:32.269,128,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,236,51,204,
2015/07/18 18:40:32.269,128,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,236,51,204,
2015/07/18 18:40:32.510,128,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,237,51,204,
2015/07/18 18:40:32.512,128,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240,51,204,
2015/07/18 18:40:32.512,128,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240,51,204,
2015/07/18 18:40:32.514,127,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240,51,204,
2015/07/18 18:40:32.514,127,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,241,51,204,
2015/07/18 18:40:32.635,128,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,243,51,204,
2015/07/18 18:40:32.635,128,0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,243,51,204,
//^this accumulated number is not correct
class Program
{
static BlockingCollection<int> mQ = new BlockingCollection<int>();
static void Main(string[] args)
{
Thread rxThread = new Thread(rxThreadFunc);
rxThread.Priority = ThreadPriority.Highest;//this causes problem
rxThread.Start();
Thread procThread = new Thread(dataProc);
procThread.Start();
Console.ReadLine();
}
static public void rxThreadFunc()
{
for (int i = 0; i < 10; i++)
{
mQ.Add(i);
}
}
static public void dataProc()
{
foreach (int outData in mQ.GetConsumingEnumerable())
{
Console.WriteLine(outData);
}
}
}
foreach (byte[] outData in _taskQ.GetConsumingEnumerable())
{
using(StreamWriter fwriter=new StreamWriter("C:\\testsave\\dataProc",true))
{
for (int i = 0; i < datalen; i++)
{
fwriter.Write(outData[i]);
fwriter.Write(",");
}
fwriter.Write("\n");
}
}
rxFrame = new FrameStruct((int)m_lMaxFrame);