简体   繁体   English

从线程内更新datagridview会导致错误C#Winform

[英]updating datagridview from within a thread causes error c# winform

I am writing a C# winform that uses a datagridview object. 我正在编写一个使用datagridview对象的C#winform。 At a certain point in the program I need to update said datagridview from within a thread. 在程序的某个点上,我需要从线程内更新所述datagridview。 This causes the program to throw an unhandled exception saying that object reference not set to an instance of an object, and makes the datagridview turn into the error image of a white box with an red X in it. 这导致程序抛出未处理的异常,该异常表示对象引用未设置为对象的实例,并使datagridview变成带有红色X的白色框的错误图像。

Specifically what I am trying to do in this case is update values in the rows, by removing the rows and updating the statistical values and reinserting the rows. 具体来说,在这种情况下,我要尝试的是通过删除行并更新统计值并重新插入行来更新行中的值。

I do this in a separate function that the thread calls and it updates two rows in the datagridview every time. 我在线程调用的单独函数中执行此操作,并且每次都会更新datagridview中的两行。

Here is the code for my update function: 这是我的更新功能的代码:

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

The stranger part of this is that I seem to be unable to catch the exception, and it happens inconsistently, as in sometime it fails the first time it tries to update, and other times it fails on the first try. 奇怪的是,我似乎无法捕捉到该异常,并且它不一致地发生,因为有时它在第一次尝试更新时失败,而有时它在第一次尝试时失败。

Any help would be greatly appreciated, 任何帮助将不胜感激,

Thanks, 谢谢,

-Jake -杰克

This may cause due to race problem. 这可能是由于race问题引起的。 In other words, one thread (likely the main thread) tries to paint the grid based on its current list of rows while the other thread infers and manipulates it. 换句话说,一个线程(可能是主线程)试图根据其当前行列表来绘制网格,而另一个线程进行推断和操作。 Moreover, I guess you have turned off CheckForIllegalCrossThreadCalls to be able to manipulate the grid directly over threads. 而且,我想您已经关闭CheckForIllegalCrossThreadCalls以便能够直接在线程上操纵网格。 If it is, this is the main cause of the problem. 如果是这样,这就是问题的主要原因。 Anyway, the possible solution is to use BeginInvoke to indirectly work with the control: 无论如何,可能的解决方案是使用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);
   }
}

EDIT: 编辑:

I thought statsData is a DataGridView . 我以为statsDataDataGridView Based on OP's comment it is a DataTable . 根据OP的注释,它是一个DataTable So, I tailored the answer to reflect this fact. 因此,我量身定制了答案以反映这一事实。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM