启动两个线程按顺序运行它们,而不是同时运行它们

时间:2013-04-17 11:52:37

标签: c#

我有一个控制窗体的主线程,按下一个按钮就会执行两个线程。一个用于记录信息,另一个用于读取信息。将这些放在线程中的想法是使用户能够在执行时与界面进行交互。

这是两个线程的创建;

Thread recordThread = new Thread(() => RecordData(data));
recordThread.Name = "record";
recordThread.Start();

Thread readThread = new Thread(() => ReadData(data));
readThread.Name = "read";
readThread.Start();

数据只是一个数据对象,用于存储录制过程中记录的数据。

我面临的问题是第一个线程执行正常,第二个线程拒绝运行,直到第一个线程完成。在第二个线程函数中放置一个断点, ReadData 让我知道只有在第一个线程完成所有记录后才会调用它。

我一直试图解决这个问题几个小时了,我无法理解为什么会这样做。添加;

while(readThread.IsAlive) { }

在启动之后将暂停执行任何操作,并且状态为正在运行。但它不会采用给定的方法。

有什么想法吗?

修改: 线程调用的两个函数是;

    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;
    }

2 个答案:

答案 0 :(得分:1)

看起来你的阅读/写作之间存在竞争条件。在您的第一个线程中,您在向其添加数据时锁定对象,在第二个线程中,您尝试对其进行独占锁定以开始读取。但是,问题是第一个线程的执行速度太快,以至于第二个线程永远无法获得锁定。

此问题的解决方案实际上取决于您在此之后的行为。如果您希望在每次写入后都能获得连续读取,那么您需要做的是控制读/写操作之间的执行,例如

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++;
    }
}

答案 1 :(得分:0)

您可以尝试在RecordData中添加Sleep吗? 也许只是你的(mono 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);