启动两个线程按顺序运行它们,而不是同时运行
本文关键字:运行 顺序 两个 线程 启动 | 更新日期: 2023-09-27 18:09:42
我有一个主线程,这是控制窗口窗体,在按下一个按钮两个线程被执行。一个用于记录信息,另一个用于读取信息。把这些放在线程中的想法是让用户能够在执行的时候与接口交互。
下面是两个线程的创建;
Thread recordThread = new Thread(() => RecordData(data));
recordThread.Name = "record";
recordThread.Start();
Thread readThread = new Thread(() => ReadData(data));
readThread.Name = "read";
readThread.Start();
data是一个简单的data -object,用于存储记录过程中记录的数据。
我面临的问题是第一个线程执行得很好,第二个线程拒绝运行,直到第一个线程完成。在第二个线程函数中放置一个断点,ReadData让我知道它只在第一个线程完成所有记录后被调用。
我已经尝试解决这个问题几个小时了,我不明白为什么它会这样做。添加一个;
while(readThread.IsAlive) { }
在start之后的将停止之后的任何执行,并且它的状态是Running。但是它不会转到给定的方法。
任何想法?
编辑:线程调用的两个函数是:
private void RecordData(Data d)
{
int i = 0;
while (i < time * freq)
{
double[] data = daq.Read();
d.AddData(data);
i++;
}
}
private void ReadData(Data d)
{
UpdateLabelDelegate updateData =
new UpdateLabelDelegate(UpdateLabel);
int i = 0;
while (i < time * freq)
{
double[] data = d.ReadLastData();
this.Invoke(updateData, new object[] { data });
i++;
}
}
data对象在被调用的两个函数中都有锁;ReadLastData和Read.
下面是Data对象中的方法。
public void AddData(double[] data)
{
lock (this)
{
int i = 0;
foreach (double d in data)
{
movementData[i].Add(d);
i++;
}
}
}
public double[] ReadLastData()
{
double[] data = new double[channels];
lock (this)
{
int i = 0;
foreach (List<double> list in movementData)
{
data[i] = list[list.Count - 1];
}
}
return data;
}
看起来你的读/写之间有一个竞争条件。在第一个线程中,您锁定对象,同时向其添加数据,在第二个线程中,您尝试获得对其的独占锁以开始读取。然而,问题是第一个线程执行得如此之快,以至于第二个线程从来没有真正有机会获得锁。
这个问题的解决方案实际上取决于你在这里追求什么样的行为。如果你希望在每次写操作之后得到一个连续的读操作,那么你需要做的是控制读/写操作之间的执行,例如
static AutoResetEvent canWrite = new AutoResetEvent(true); // default to true so the first write happens
static AutoResetEvent canRead = new AutoResetEvent(false);
...
private void RecordData(Data d)
{
int i = 0;
while (i < time * freq)
{
double[] data = daq.Read();
canWrite.WaitOne(); // wait for the second thread to finish reading
d.AddData(data);
canRead.Set(); // let the second thread know we have finished writing
i++;
}
}
private void ReadData(Data d)
{
UpdateLabelDelegate updateData =
new UpdateLabelDelegate(UpdateLabel);
int i = 0;
while (i < time * freq)
{
canRead.WaitOne(); // wait for the first thread to finish writing
double[] data = d.ReadLastData();
canWrite.Set(); // let the first thread know we have finished reading
this.Invoke(updateData, new object[] { data });
i++;
}
}
您可以尝试在RecordData中添加Sleep吗?也许这只是你的(单cpu?? ?) windows操作系统不让第二个线程得到它的cpu资源。
不要这样做:锁(这)
不如这样做:
private object oLock = new object();
[...]
lock (this.oLock)
编辑:你能试试这样的电话吗?
Thread recordThread = new Thread((o) => RecordData((Data)o));
recordThread.Name = "record";
recordThread.Start(data);