0

我正在编写一个使用 datagridview 对象的 C# winform。在程序的某个时刻,我需要从线程中更新所述数据网格视图。这会导致程序抛出未处理的异常,指出对象引用未设置为对象的实例,并使 datagridview 变成带有红色 X 的白框的错误图像。

具体来说,在这种情况下,我要做的是更新行中的值,方法是删除行并更新统计值并重新插入行。

我在线程调用的单独函数中执行此操作,并且每次都会更新 datagridview 中的两行。

这是我的更新功能的代码:

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问题引起的。换句话说,一个线程(可能是主线程)尝试根据其当前的行列表绘制网格,而另一个线程推断和操作它。此外,我猜你已经关闭了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 回答