Это многопоточный сценарий.
- Основной поток обрабатывает события приложения и пользовательского интерфейса и запускает новый поток для выполнения некоторых фоновых операций.
- Фоновый поток загружает данные из файлов в таблицу данных строго типизированного набора данных.
DataGridView
привязывается к этому DataTable
. - Как только данные готовы, «фоновый» поток вызывает
refresh()
функцию DataGridView
в форме.
Если строк больше, то что умещается на одном экране и должна появиться вертикальная полоса прокрутки: происходит сбой сетки. Всегда отображаются новые линии данных.Ошибка возникает только при наличии достаточного количества строк для отображения полосы прокрутки (см. Изображение ниже).
Я использую .NET 3.5.В Windows XP вылетает целое приложение.На Win 7 (64 бит) только сетка перестает отвечать, но как только я изменяю размер окна, появляется полоса прокрутки, и все в порядке.
Соответствующие части кода прикреплены ниже.
Операция обновления сетки в файле .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
аналогичным образом, но из другого потока.
Но новые строки данных непоявляются, пока я, скажем, не изменю размер окна.
Что поднимает вопрос, как правильно обновить dataTable
из другого потока?