我正在研究一个模拟代码,我有一个“项目”,可以进行大量的模拟。您可以选择一次运行一个,也可以按顺序运行它们。在这种特殊情况下,我有18个模拟逐个运行,整个过程大约需要20秒。
简而言之,在表单上按下按钮,会发生以下操作:
1)创建模拟对象
2)执行模拟启动命令
3)将模拟数据写入文件
4)配置模拟对象
5)更新保存模拟列表的DataGridView(将“Processing”重写为“Complete”)
6)更新用户控制中的进度条值
7)刷新用户控制。
粗略的源代码如下:
for (int i = 0; i < dataSet.Count; i++)
{
using (Processor p = new Processor())
{
bool didTestPass = p.RunTest(dataSet[i]);
if (didTestPass)
dataGridViewProcessList.Rows[i].Cells[5].Value = "Run complete.";
else
dataGridViewProcessList.Rows[i].Cells[5].Value = "Run completed with errors.";
}
progressBarRuntime.Value = ((i+1) / dataSet.Count) * 100;
this.Refresh();
this.OnUpdateMainForm(this, null);
}
我发现,如果你仍然在应用程序的焦点范围内,所有18个模拟运行正常。但是,如果您放弃焦点(例如,切换到另一个程序),它在第8次模拟时始终表现不正常。我说的不规律,因为它的行为不同:
通过Visual Studio进行调试时,表单会暂时冻结,然后突然处理所有剩余的模拟,并且进度条会捕捉到完整。
当作为独立程序运行时,它会直接崩溃到桌面。没有警告,没有例外,一无所获。
我还发现,如果我保持专注并让它达到,例如,模拟14,然后从计划中删除焦点,它将立即表现出上述行为。
我对Windows窗体处于活动状态时执行大量计算工作的概念并不是特别熟悉。起初我觉得可能需要刷新表单(因为这一切都发生在UserControl上)但是当我发布一个强制表单Refresh()
的事件时,我没有看到任何区别。
答案 0 :(得分:0)
我最终发现我的问题的根源是我在界面的主线程上执行工作,结果导致我的程序挂起并崩溃到桌面。
我创建了BackgroundWorker
并将我的工作代码放入DoWork
事件中,然后将ProgressBar
指标更新移至ProgressChanged
事件中。
有关BackgroundWorker
的详细信息及其在MSDN的实施情况。
简而言之,从我那里学到的教训是,如果表单中的活动花费的时间超过几秒钟,则应使用BackgroundWorker
来完成,以防止挂起界面。