[英].NET 3.5 WinForms - DataGridView crashes on refresh(). Is it a bug?
這是一個多線程場景。
DataGridView
綁定到該DataTable
。DataGridView
的refresh()
function。如果有更多的行,那么適合一個屏幕的內容和垂直滾動條就會出現:網格崩潰。 始終顯示新的數據線。 只有當有足夠的行來顯示滾動條時才會發生錯誤(見下圖)。
我使用 .NET 3.5。 在 Windows XP 中,它會使整個應用程序崩潰。 在 Win 7(64 位)上,只有網格變得無響應,但是一旦我調整 window 的大小,滾動條就會出現,一切都很好。
代碼的相關部分附在下面。
表單的.cs文件中的網格刷新操作:
public void ThreadSafeRebindGrids()
{
SimpleCallBack callBackHandler = new SimpleCallBack(RebindGrids);
this.BeginInvoke(callBackHandler);
}
public void RebindGrids()
{
gridCurrentResults.Refresh(); // The problematic DataGridView refresh()
gridAllResults.Refresh();
}
public delegate void SimpleCallBack();
“后台”線程中的更新部分:
void Maestro32_SampleFinished(object sender, MeasurementEvents.SampleFinishedEventArgs e)
{
//--- Read new results
ParentForm.ThreadSafeSetStatusInfo("Processing results for sample no. " + e.SampleNo.ToString() + "...");
CurrentMeasurement.ReadSpeResults(); // Updating the DataTable in the strongly typed DataSet (see below)
ParentForm.ThreadSafeRebindGrids(); // Refresh the DataGridView
ParentForm.ThreadSafeRefreshNumbers();
}
與“后台”線程相關的對象直接引用了DataSet
( UiDataSource
)。 DataTable
( CurrentSamples
) 以下列方式更新:
/// <summary>
/// Adds a new sample to the CurrentSamples table of the UiDataSet.
/// </summary>
/// <param name="sample">The new sample to be added to the table.</param>
/// <param name="serial">The serial number of the sample being added</param>
private void AddSampleToCurrentResults(SampleData sample, int serial)
{
UiDataSource.CurrentSamples.AddCurrentSamplesRow(serial,
sample.MeasurementDate,
(uint)Math.Round(sample.SampleCountSum),
true, //--- Set the checkbox checked
sample.LiveTime,
sample.RealTime);
}
DataGridView
選項:
//
// gridCurrentResults (generated)
//
this.gridCurrentResults.AllowUserToAddRows = false;
this.gridCurrentResults.AllowUserToDeleteRows = false;
this.gridCurrentResults.AllowUserToOrderColumns = true;
this.gridCurrentResults.AllowUserToResizeRows = false;
this.gridCurrentResults.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.gridCurrentResults.AutoGenerateColumns = false;
this.gridCurrentResults.CausesValidation = false;
this.gridCurrentResults.ColumnHeadersHeight = 25;
this.gridCurrentResults.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.selectedCol,
this.SampleNoCol,
this.MeasuredValueCol,
this.liveTimeCol,
this.realTimeDataGridViewTextBoxColumn,
this.AtTimeCol});
this.gridCurrentResults.DataMember = "CurrentSamples";
this.gridCurrentResults.DataSource = this.uiDataSource;
this.gridCurrentResults.Location = new System.Drawing.Point(11, 24);
this.gridCurrentResults.Margin = new System.Windows.Forms.Padding(8);
this.gridCurrentResults.Name = "gridCurrentResults";
this.gridCurrentResults.RowHeadersVisible = false;
this.gridCurrentResults.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
this.gridCurrentResults.ShowEditingIcon = false;
this.gridCurrentResults.Size = new System.Drawing.Size(534, 264);
this.gridCurrentResults.TabIndex = 0;
this.gridCurrentResults.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.gridCurrentResults_CellContentClick);
如果我在某個地方犯了錯誤,請指出給我。
@ChrisF:
我嘗試刪除refresh()
語句,因為我所做的與你建議的幾乎相同。 唯一的區別是數據綁定,它看起來像:
this.dataGridView.DataSource = this.dataSet;
this.dataGridView.DataMember = "dataTable";
我以類似的方式更新dataTable
,但來自另一個線程。
但是新的數據線直到我調整 window 的大小時才會出現。
這引發了我如何從另一個線程正確更新dataTable
的問題?
我猜這個問題與 WinForms 在 STA model 中的線程工作方式有關。 基本上,您正在訪問的 DataTable 位於某個地方,這可能在我們上面看到的表格中。 那么,當您從另一個線程更新 DataTable 時,哪個線程獲取綁定所需的事件? 很可能是您從中更新它的線程,並且表單的線程不知道正在進行的更改。 因此,您只需在表單本身上調用對 DataTable 的任何調用,它就可以正確接收事件:
this.Invoke(() => {
// any calls involving DataTable
});
這似乎是倒退的,但請記住,在“企業”情況下,您可能會通過多個適配器訪問該數據集。 因此,您的更新線程本身將有一個適配器,您的 GUI 也將有自己的。 另一種解決方案是使用BindingList
,我相信它對這種情況具有線程兼容性,但不要引用我的話。
對於額外的功勞,這也可以在崩潰之前解釋您的問題。 通過從后台線程訪問DataGridView
,您可以進行跨線程操作。
我不會打電話:
gridCurrentResults.Refresh(); // The problematic DataGridView refresh()
gridAllResults.Refresh();
隨着數據集變得越來越大,這些將花費越來越長的時間。
我編寫了一個使用DataGridView
來顯示 mp3 文件信息的應用程序。 我將DataGridView
的DataSource
設置為DataTable
:
this.dataGridView.DataSource = this.dataTable;
然后只需將新信息添加到DataTable
:
this.dataTable.Rows.Add(row);
這會自動更新DataGridView
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.