2013-10-06 34 views
0

我在寫一個使用datagridview對象的C#winform。在程序中的某個點,我需要從線程內更新所述datagridview。這會導致程序拋出未處理的異常,指出對象引用未設置爲對象的實例,並使datagridview變成帶有紅色X的白色框的錯誤圖像。從線程內更新datagridview會導致錯誤c#winform

具體而言,我在這種情況下要做的是更新行中的值,方法是刪除行並更新統計值並重新插入行。

我在線程調用的單獨函數中執行此操作,並且每次更新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); 
    } 

這樣做的陌生人的是,我似乎無法趕上例外,而且它發生不一致,在某個時候它不能在第一時間它會嘗試更新,有時會在第一次嘗試時失敗。

任何幫助將不勝感激,

感謝,

-Jake

回答

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

編輯:

我想statsDataDataGridView。根據OP的評論,這是一個DataTable。所以,我定製了答案來反映這個事實。

+0

statData是一個dataTable對象,並沒有BeginInvoke方法。你認爲我應該用datagridview對象本身來使用statData作爲綁定數據嗎? –

+0

我使用了我正在使用的datagridviews的調用者,並且只是圍繞此函數調用進行調用,以使它更簡單,並且工作正常!謝謝,我認爲它與線程同時寫入有關,但我沒有意識到我可以用它來修復它。我在應用程序的其他部分使用了調用,但我從來沒有想過這樣嘗試。再次感謝! –

+0

@JakeGearhart感謝您的澄清。我只是更新了答案,以反映你的看法。 – Alireza