WindowsMo​​bile:从DialogForm处理异常后应用程序退出

时间:2009-04-07 08:26:22

标签: c# winforms exception windows-mobile

我有以下简单方案:

带有Button的DialogForm,Button_click会抛出异常。

带有按钮和标签的MainForm,在单击中我在Catch块内显示DialogForm的新实例。

如果我在常规WinForms中运行此设置,我可以按预期捕获异常。

如果我在WinMobile中运行它(我已在WM5和WM6 Pro上测试过),我可以通过调试器看到Catch块进入但是Exception继续向上传播并且应用程序死掉了。

MainForm中的代码如下所示:

try
{
   using (DialogForm frm = new DialogForm())
   {
     DialogResult r = frm.ShowDialog();
     label1.Text = r.ToString();
  }
}
catch (Exception ex)
{
  label1.Text = ex.Message;
}

编辑:

我进一步调查了一下,在这段代码和Application.Run()周围有一个catch {}块,应用程序仍然退出。

显然它是一个失控的异常,被抓住并处理得很好。但在此操作之后,它看起来像应用程序执行不需要的Exit()。

8 个答案:

答案 0 :(得分:5)

经过修修补补后,我找到了有效的方法:

try {
  // show Dialog that Throws
}
catch (Exception ex) {
  label1.Text = ex.Message;
  Application.DoEvents();  // this solves it
}

对于任何能告诉我为什么 DoEvents()是必要的人,赏金仍然是开放的。

答案 1 :(得分:5)

您需要'DoEvents'的原因是,当表单仍然可用时,这会清除消息队列。

正在发生的事情是仍有消息等待处理抛出异常的表单。通过在这里调用'DoEvents',您可以在使用块清理表单并停止处理队列中的消息之前对它们进行处理。

答案 2 :(得分:2)

我能找到的最好的信息就是你正在调用ShowDialog()。

我尝试使用Reflector,但它没有处理CF dll。因此,最好的比较是查看主要的非CF文件。在其中,如果跟踪ShowDialog()函数,它最终会调用Application.RunDialog(form)。在那里,它创建一个新的线程上下文并为对话框窗口运行自己的消息循环。

由于我无法查看实际的CF DLL,我只能采取“有根据的猜测”。它似乎与异常发生在单独的消息循环上并且除非您通过DoEvents()处理应用程序的消息队列之外无法正确捕获这一事实有关。

基本上,ShowDialog()导致在单独的消息循环上创建异常,除非你调用DoEvents(),否则它被捕获的事实无法正确处理。

如果您尝试常规Show()会发生什么?你还需要DoEvents吗?我没有测试环境,所以我只能建议您尝试一下。如果你把它改成Show()并且不再需要DoEvents(),我想我们肯定会知道我是否是对的。

答案 3 :(得分:2)

https://connect.microsoft.com/VisualStudio/feedback/details/94356/modal-windows-in-net-compact-framework-application-stop-working-if-unhandled-exception-on-modal-dialog-is-raised#tabs

在紧凑框架2.0中,这是一个公认的问题...... 他们不在乎...

如果你在一次尝试中使用showdialog,一旦你发现异常,showdialod就不再有效了....

答案 4 :(得分:1)

虽然编程文档会说明以下构造是不必要的,但我发现有时我必须使用以下内容。

try
{
 using (DialogForm frm = new DialogForm())   
 {     
       DialogResult r = frm.ShowDialog();
       label1.Text = r.ToString();  
 }
}
catch (Exception ex)
{
    label1.Text = ex.Message;
}
catch
{
    label1.Text = "Unknown Exception";
}

答案 5 :(得分:1)

也许挂钩AppDomain.CurrentDomain.UnhandledException(连同Joel的提示)解决了你的异常问题?可能类似于this other .NET answer

我使用以下代码

    try
    {
        AppDomain.CurrentDomain.UnhandledException +=
            (object sender, UnhandledExceptionEventArgs e) =>
            {
                CrashOn((Exception)e.ExceptionObject, e.IsTerminating);
            };
        var mainWindow = new MainWindow();
        MobileDevice.Hibernate += (sender, e) => { mainWindow.Hibernate(); };
        Application.Run(mainWindow);
    }
    catch (Exception huh)
    {
        CrashOn(huh, false);
    }

在我WM6 Professional twitter clientProgram.Main()中。这里CrashOn()方法将异常信息保存到磁盘并启动崩溃恢复可执行文件。然后显示客户端崩溃的信息,可以选择向我发送异常信息,并使用退出或重新启动客户端的选项。

答案 6 :(得分:1)

根据其他答案和我对所需DoEvents的评论:您是否尝试检查原始的catch语句label1.InvokeRequiredtrue

如果是这样,你可能会遇到某种与多线程相关的竞争条件,因为你将label1.Text设置为从另一个线程抛出的异常类的属性?

在常规.NET 1.0中,这通常只是工作,而不应该。在以后的版本中,忽略InvokeRequired == true会导致异常。我不确定Compact Framework如何处理这种“违规行为”。也许它只是存在过程呢?

答案 7 :(得分:0)

我记得dot net有一个默认异常处理程序,当异常越过特定边界时会触发该异常处理程序。正是这个处理程序导致您的应用退出。我记得有一段时间回顾这个问题,但遗憾的是不再能够访问代码。至于.NET和.NET CF之间的行为差​​异,这是因为两个处理帧的方式不同(CF中的帧可能没有父级或类似的东西)。

你可以挂钩这个默认的异常处理并做任何事情...我认为我实现的代码是这样的:Unhandled Exceptions