这是一个多线程场景。
DataGridView
绑定到DataTable
。refresh()
的{{1}}函数。如果有更多行,那么适合一个屏幕并显示垂直滚动条:网格崩溃。始终显示新的数据线。仅当有足够的行显示滚动条时才会出现错误(请参见下图)。
我使用的是.NET 3.5。在Windows XP中,它会崩溃整个应用程序。在Win 7(64位)上,只有网格没有响应,但是一旦我调整窗口大小,就会出现滚动条,一切都很好。
代码的相关部分如下。
表单的.cs文件中的网格刷新操作:
DataGridView
“后台”主题中的更新部分:
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
如果我在某处犯了错误,请指出我。
@ChrisF:
我尝试删除 //
// 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);
语句,因为我的建议与您建议的完全相同。唯一的区别是数据绑定,它看起来像:
refresh()
我以类似的方式更新this.dataGridView.DataSource = this.dataSet;
this.dataGridView.DataMember = "dataTable";
,但是从另一个线程更新。
但是,在我调整窗口大小之前,新数据行不会出现。
这提出了如何从另一个线程正确更新dataTable
的问题?
答案 0 :(得分:4)
我猜这个问题与WinForms如何在STA模型中进行线程化有关。基本上,您访问的DataTable位于某处,这可能在我们上面看到的表单中。那么,当您从另一个线程更新DataTable时,哪个线程获取绑定所需的事件?可能是您更新它的线程,并且表单的线程不知道正在进行的更改。因此,您只需要调用对DataTable的任何调用到表单本身,因此它可以正确地接收事件:
this.Invoke(() => {
// any calls involving DataTable
});
似乎倒退了,但在“企业”情况下请记住,您可能正在通过多个适配器访问该数据集。因此,您的更新线程将拥有自己的适配器,您的GUI也将拥有自己的适配器。另一种解决方案是使用BindingList
,我相信这种情况具有线程兼容性,但不要引用我。
为了获得额外的功劳,这也可以在崩溃之前解释您的问题。通过从后台线程访问DataGridView
,您可以进行跨线程操作。
答案 1 :(得分:0)
我不打电话:
gridCurrentResults.Refresh(); // The problematic DataGridView refresh()
gridAllResults.Refresh();
随着数据集变得越来越大,这些将逐渐变得越来越长。
我编写了一个使用DataGridView
来显示mp3文件信息的应用程序。我将DataSource
的{{1}}设置为DataGridView
:
DataTable
然后只需将新信息添加到this.dataGridView.DataSource = this.dataTable;
:
DataTable
这会自动更新this.dataTable.Rows.Add(row);
。