从后台线程奇怪的行为更新 datagridview
Posted
技术标签:
【中文标题】从后台线程奇怪的行为更新 datagridview【英文标题】:Update datagridview from background thread odd behavior 【发布时间】:2012-06-24 16:20:47 【问题描述】:我有一些数据,我在一项任务中对其进行了更新:该应用程序目前对于一个想法来说是一个黑客,因此对代码表示歉意。
Task.Factory.StartNew(() =>
dataGridView1.BeginInvoke((Action)(() =>
dataGridView1.SuspendLayout();
));
dataSet1.Reset();
da.Fill(dataSet1);
dataGridView1.BeginInvoke((Action)(() =>
dataGridView1.DataSource = dataSet1.Tables[0];
dataGridView1.Columns[0].Visible = false;
dataGridView1.Columns[1].Width = 50;
dataGridView1.ResumeLayout();
));
).ContinueWith(task =>
if (dataSet1.Tables[0].Rows.Count > 0)
if (lastcount != dataSet1.Tables[0].Rows.Count)
lastcount = dataSet1.Tables[0].Rows.Count;
if (lastcount == 0)
NotifyWithMessage("The items have been cleared", "Items cleared");
else
NotifyWithMessage(String.Format("There are 0 new items in your monitor", dataSet1.Tables[0].Rows.Count));
);
现在,代码基本上可以工作了。没有错误,这很好..
当它在任务之外更新时,datavgridview 根本没有闪烁,当我在调试中运行它时,它非常小,并且在黑客可以接受的范围内......当我在调试之外运行它时......这非常明显!暂停和恢复布局根本没有任何区别。我需要线程中的代码,因为 UI 在没有响应的情况下是块状的 - 虽然它是可以接受的,但它现在的刷新很糟糕。
我的 Datagridview 是根据单元格颜色自定义颜色的,但是,我只是不明白为什么调试和发布之间存在差异,我希望性能反过来!
(我试过 Invoke 和 BeginInvoke...)
我看了看Horrible redraw performance of the DataGridView on one of my two screens
而且在debug下,这个一点也不闪烁,一点点都没有……在release条件下,有一个可笑的闪烁……
我能做什么?
【问题讨论】:
【参考方案1】:在后台启动一项填充数据集的任务,完成此任务后,您将执行 BeginInvoke,在此暂停布局、分配数据并恢复。
使用您现在拥有的版本,执行代码路径的可能性非常多,很难预测会发生什么。
渲染必须在 UI 线程上,所以你所能做的就是尝试优化它的代码。我会按照文章开头所述执行异步部分。
【讨论】:
我认为上面的代码确实在一个单独的线程中填充了数据集..因为它是在一个任务中完成的..【参考方案2】:最后我做了什么: 我将查询重新放入一个新的数据集中,如果计数相同,那么我没有更新网格,如果计数发生了变化,我做了。
timer1.Stop();
Task<Boolean>.Factory.StartNew(() =>
DataSet t = new DataSet();
//_dataSet1.Reset();
Boolean ok = false;
Int16 retries = 0;
while (!ok && retries<3)
try
da.Fill(t);
ok = true;
catch
retries++;
Thread.Sleep(1000);
//if (!ok) throw new Exception("DB error");
if (!ok) return false;
try
if (t.Tables.Count > 0 && t.Tables[0].Rows.Count != _lastcount)
_dataSet1 = t;
_lastcount = t.Tables[0].Rows.Count;
return true;
catch
return false;
).ContinueWith(task =>
if (task.IsFaulted)
SQLFailed();
return;
if (!task.Result) return;
Invoke((Action) (() =>
dataGridView1.DataSource = _dataSet1.Tables[0];
dataGridView1.Columns[0].Visible = false;
dataGridView1.Columns[1].Width = 50;
));
if (_lastcount == 0)
NotifyWithMessage("The items have been cleared", "Items cleared");
else
NotifyWithMessage(String.Format("There are 0 new items in your monitor", _lastcount));
);
timer1.Start();
【讨论】:
以上是关于从后台线程奇怪的行为更新 datagridview的主要内容,如果未能解决你的问题,请参考以下文章
Xcode7:此应用程序正在从后台线程修改自动布局引擎,这可能导致引擎损坏和奇怪的崩溃
从后台线程执行时关闭 WithCompletionHandler 有奇怪的结果
Xamarin Forms - 从 2017 年到 2019 年更新 Visual Studio 后 iOS 上的奇怪行为