我正在尝试在从 sql 服务器查询的网格上显示一些信息。数据收集可能需要大约 10 秒,所以我不想锁定 UI 线程。
我目前有如下代码:
ThreadPool.QueueUserWorkItem(DataUpdateThread, new UpdateParams(year));
private struct UpdateParams
{
internal string year;
internal UpdateParams(string year)
{
this.year = year;
}
}
private void DataUpdateThread(object state)
{
DataTable dTable = new DataTable();
try
{
this.Invoke((MethodInvoker)delegate
{
//stop data editing on the grid
//scrolling marquee for user
marquee.Visible = true;
marquee.Enabled = true;
grdMain.Visible = false;
grdMain.DataSource = null;
});
UpdateParams parameters = (UpdateParams)state;
dTable = GetData(parameters.year);
}
catch (Exception ex)
{
this.Invoke((MethodInvoker)delegate
{
//log error + end user message
});
}
finally
{
this.Invoke((MethodInvoker)delegate
{
grdMain.DataSource = dTable;
grdMainLevel1.RefreshData();
marquee.Visible = false;
marquee.Enabled = false;
grdMain.Visible = true;
});
}
}
这在大多数情况下都有效,除非它所在的表单在更新完成之前关闭,否则它将因错误而崩溃:
在创建窗口句柄之前,不能对控件调用 Invoke 或 BeginInvoke。
我理解错误将是因为表单不再存在,所以当 finally 部分尝试在 UI 线程上调用该方法时它不能。
有没有更好的方法来做这件事?我想我可以处理调用错误,但它看起来很乱,我想我可能错过了一个更简单的方法。