0

datagridview オブジェクトを使用する C# winform を作成しています。プログラムのある時点で、スレッド内から上記の datagridview を更新する必要があります。これにより、プログラムはオブジェクト参照がオブジェクトのインスタンスに設定されていないことを示す未処理の例外をスローし、datagridview を赤い X が付いた白いボックスのエラー イメージに変えます。

具体的には、この場合、行を削除して統計値を更新し、行を再挿入することで、行の値を更新します。

スレッドが呼び出す別の関数でこれを行い、毎回 datagridview の 2 つの行を更新します。

私の更新機能のコードは次のとおりです。

private void updateStats(int binNumber)
    {
        binNumber *= 2;//has to multiply by 2 because every bin has two rows in this table
        if (statsData.Rows.Count >= (binNumber + 1))
        {
            statsData.Rows.RemoveAt(binNumber);
            //number does not change because the index was just decreased by one
            statsData.Rows.RemoveAt(binNumber);//because every bin requires two rows
        }
        Bin bin = bins[binNumber / 2];
        List<double> realETempData = new List<double>();
        List<double> imagETempData = new List<double>();
        List<double> realAlphaTempData = new List<double>();
        List<double> imagAlphaTempData = new List<double>();
        //updates average and std dev values
        foreach (MinSearchData dataPoint in bin.binData)
        {
            realETempData.Add(dataPoint.RealE);
            imagETempData.Add(dataPoint.ImagE);
            realAlphaTempData.Add(dataPoint.RealAlpha);
            imagAlphaTempData.Add(dataPoint.ImagAlpha);
        }
        bin.AverageRealE = realETempData.Average();
        bin.AverageImagE = imagETempData.Average();
        bin.StdDevRealE = calculateStandardDeviation(realETempData);
        bin.StdDevImagE = calculateStandardDeviation(imagETempData);
        bin.AverageRealAlpha = realAlphaTempData.Average();
        bin.AverageImagAlpha = imagAlphaTempData.Average();
        bin.StdDevRealAlpha = calculateStandardDeviation(realAlphaTempData);
        bin.StdDevImagAlpha = calculateStandardDeviation(imagAlphaTempData);
        realETempData.Clear();
        imagETempData.Clear();
        realAlphaTempData.Clear();
        imagAlphaTempData.Clear();
        DataRow myRow = statsData.NewRow();

        myRow[0] = bin.BinName;
        myRow[1] = "Real";
        myRow[2] = bin.AverageRealAlpha;
        myRow[3] = bin.StdDevRealAlpha;
        myRow[4] = bin.AverageRealE;
        myRow[5] = bin.StdDevRealE;
        statsData.Rows.InsertAt(myRow, binNumber);

        DataRow myRow2 = statsData.NewRow();
        myRow2[0] = "";
        myRow2[1] = "Imaginary";
        myRow2[2] = bin.AverageImagAlpha;
        myRow2[3] = bin.StdDevImagAlpha;
        myRow2[4] = bin.AverageImagE;
        myRow2[5] = bin.StdDevImagE;
        statsData.Rows.InsertAt(myRow2, binNumber + 1);
    }

これの奇妙な部分は、例外をキャッチできないように見えることであり、最初に更新しようとしたときに失敗することもあれば、最初の試行で失敗することもあるため、一貫性がありません。

どんな助けでも大歓迎です、

ありがとう、

-ジェイク

4

1 に答える 1

2

不具合により発生する場合がありraceます。つまり、1 つのスレッド (おそらくメイン スレッド) が現在の行のリストに基づいてグリッドを描画しようとし、もう 1 つのスレッドがそれを推測して操作します。CheckForIllegalCrossThreadCallsさらに、スレッドを介してグリッドを直接操作できるようにオフにしたと思います。そうであれば、これが問題の主な原因です。とにかく、考えられる解決策はBeginInvoke、コントロールを間接的に操作するために使用することです。

private void updateStats(int binNumber)
{
  datagridview1.BeginInvoke(new MethodInvoker(() =>
  {
        binNumber *= 2;//has to multiply by 2 because every bin has two rows in this table
        if (statsData.Rows.Count >= (binNumber + 1))
          ....
          ....
          ....        
        myRow2[5] = bin.StdDevImagE;
        statsData.Rows.InsertAt(myRow2, binNumber + 1);
   }
}

編集:

だと思いstatsDataました DataGridView。OPのコメントに基づくと、DataTable. そのため、この事実を反映するように回答を調整しました。

于 2013-10-06T21:55:40.617 に答える