【问题标题】:Resolving crash to desktop when application loses focus解决应用程序失去焦点时桌面崩溃的问题
【发布时间】:2013-07-02 19:08:26
【问题描述】:

我正在编写一个模拟代码,其中我有一个可以容纳大量模拟的“项目”。您可以选择一次运行它们,也可以按顺序运行它们。在这个特定的案例中,我有 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() 时,我发现没有任何区别。

【问题讨论】:

    标签: c# winforms crash


    【解决方案1】:

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

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

    有关BackgroundWorker 及其实现的更多详细信息,请参见MSDN

    简而言之,我学到的教训是,如果表单中的活动需要超过几秒钟的时间,则应使用BackgroundWorker 来完成,以防止界面挂起。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-05
      • 1970-01-01
      • 2018-01-28
      • 2020-08-26
      • 1970-01-01
      相关资源
      最近更新 更多