1

Windowsフォームを制御するメインスレッドがあり、ボタンを押すと2つのスレッドが実行されます。1 つは情報を記録するために使用され、もう 1 つはそれを読み取るために使用されます。これらをスレッドに入れる背後にある考え方は、実行中にユーザーがインターフェースと対話できるようにすることです。

これが 2 つのスレッドの作成です。

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

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

データは、記録中に記録されるデータを格納する単純なデータ オブジェクトです。

私が直面している問題は、最初のスレッドが正常に実行され、2 番目のスレッドが最初のスレッドが完了するまで実行を拒否することです。2 番目のスレッド関数にブレークポイントを設定すると、ReadDataによって、最初のスレッドがすべての記録を完了した後にのみ呼び出されることがわかります。

私はこれを数時間解決しようとしてきましたが、なぜこれを行うのか理解できません。を追加します。

while(readThread.IsAlive) { }

開始直後はその後の実行を停止し、状態はRunningです。しかし、それは与えられた方法には行きません。

何か案は?

編集:スレッドによって呼び出される2つの関数は次のとおりです。

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

データオブジェクトには、呼び出される両方の関数がロックされています。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;
    }
4

2 に答える 2

1

読み取り/書き込みの間に競合状態があるようです。最初のスレッドでは、オブジェクトにデータを追加している間、オブジェクトをロックダウンし、2 番目のスレッドでは、読み取りを開始するために排他ロックを取得しようとします。ただし、問題は、最初のスレッドの実行速度が速すぎて、2 番目のスレッドが実際にロックを取得する機会がないことです。

この問題の解決策は、ここでの行動の種類によって異なります。すべての書き込み後に連続した読み取りが期待される場合は、読み取り/書き込み操作間の実行を制御する必要があります。

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++;
    }
}
于 2013-04-17T13:38:30.550 に答える