1

我正在研究一个模拟代码,其中我有一个可以容纳大量模拟的“项目”。您可以选择一次运行它们,也可以按顺序运行它们。在这个特定的案例中,我有 18 个模拟逐个运行,整个过程大约需要 20 秒。

简而言之,在表单上按下一个按钮,会发生以下动作:

1) 创建模拟对象
2) 执行模拟开始命令
3) 将模拟数据写入文件
4) 处理模拟对象
5) 更新保存模拟列表的 DataGridView (将“处理”重写为“完成”)
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().

4

1 回答 1

0

我最终发现问题的根源是我在界面的主线程上执行工作,结果导致我的程序挂起并崩溃到桌面。

我创建了一个BackgroundWorker并将我的工作代码放入DoWork事件中,然后将ProgressBar指标更新移动到ProgressChanged事件中。

有关MSDNBackgroundWorker及其实施的更多详细信息。

简而言之,我学到的教训是,如果 Form 中的活动将花费超过几秒钟的时间,则应使用 aBackgroundWorker来完成以防止挂起界面。

于 2013-07-10T17:31:03.187 回答