6

因此,我对尝试从程序自动收集数据的概念感到满意——即,当出现问题时,弹出一个对话框,要求用户发送报告。

我在 MS Visual Studio C# 中工作。

从实现的角度来看,在我的主 program.cs 文件中放置一个 try/catch 循环是否有意义,在应用程序运行的位置周围?像这样:

        try
        {
            Application.Run(new myMainForm());
        }
        catch (Exception ex)
        {
            //the code to build the report I want to send and to 
            //pop up the Problem Report form and ask the user to send

        }

或者将 try/catch 循环放在代码片段中以捕获更具体的异常类型是否有意义?(我认为不是因为这是一个新应用程序,并且放入更具体的异常捕获意味着我知道会出现什么问题......我不知道,这就是为什么上面对我来说似乎有意义.)

-阿迪娜

4

6 回答 6

9

我认为你是对的,你不会知道会出什么问题,这就是重点。

但是,您不妨考虑将处理程序添加到ThreadException事件。

上面的代码可以工作,但在某些情况下,此类代码可能会出现多线程问题,因为并非 Windows 窗体程序中的所有代码都将在主 Application.Run 循环线程中运行。

这是链接文章中的示例代码:

[STAThread]
static void Main() 
{
   System.Windows.Forms.Application.ThreadException += new ThreadExceptionEventHandler(ReportError);
   System.Windows.Forms.Application.Run(new MainForm());
}

private static void ReportError(object sender, ThreadExceptionEventArgs e)
{
   using (ReportErrorDialog errorDlg = new ReportErrorDialog(e.Exception))
   {
    errorDlg.ShowDialog();
   }
}

有关MSDN的更多文档。

在次要的一点上,使用 ThreadException 事件还允许您的主消息循环继续运行,以防异常不是致命的(即容错方案),而 try/catch 方法可能需要您重新启动主消息循环,这可能引起副作用。

于 2008-12-14T17:00:10.317 回答
1

如果您确实想自动获取堆栈跟踪,Microsoft 确实允许您通过错误报告服务提交它们。您需要做的就是从 VeriSign 注册一个数字证书并在 Microsoft 注册(免费)。

然后,Microsoft 会为您提供一个登录名,以便您从网站下载迷你转储,当用户单击“发送错误报告”时提交这些迷你转储。

尽管人们可以点击“不要发送”,但至少它是一个 Microsoft 对话框,可能不需要您自己编写代码。它将 24/7 全天候运行,您不必担心 Web 服务器的正常运行时间,您可以为用户提交解决方法详细信息,并且您可以通过 Windows Update 提供更新。

有关此服务的信息位于此“ Windows 错误报告:入门”文章中。

于 2009-08-11T10:30:29.780 回答
1

从实现的角度来看,在我的主 program.cs 文件中放置一个 try/catch 循环是否有意义,在应用程序运行的位置周围?

当然,永远。

你应该在任何关键的地方使用 Try/Catch-Blocks,这可能会引发异常。

因此,你不能真正坚持一个模式,因为你现在应该,什么时候会引发什么异常。否则这些都是未处理的异常,会让你的程序崩溃。

但是有许多异常,不需要完全停止应用程序,异常可以被吞掉,因为它们是预期的,并不需要应用程序停止。例如,使用程序移动或访问数据时出现 UnauthorizedAccessExceptions。

由于性能原因,您应该尽量使 Try/Catch-Blocks 尽可能小,并且不要使用太多。

有些使用 Try/Catch 来控制程序的执行。应尽可能完全避免这种情况,因为引发异常是性能杀手数 1。

于 2008-12-14T17:20:49.027 回答
1

在整个应用程序周围包装一个 try catch 意味着应用程序将在出错时退出。

虽然对每种方法都使用 try and catch 是很难维护的。

最佳实践是在代码单元周围使用特定的 try catch,这些代码单元将抛出特定的异常类型,例如 FormatException,并将一般异常处理留给应用程序级事件处理程序。

try
        {
            //Code that could error here
        }
        catch (FormatException ex)
        {
            //Code to tell user of their error
            //all other errors will be handled 
            //by the global error handler
        }

经验会告诉你可能出错的事情类型。随着时间的推移,您会注意到您的应用程序经常抛出有关文件访问的 IO 异常,因此您以后可能会捕获这些异常并为用户提供更多信息。

错误的全局处理程序将捕获其他所有内容。您可以通过将事件处理程序连接到两个事件 System.Windows.Forms.Application.ThreadException(请参阅 MSDN)和 AppDomain.UnhandledException(请参阅 MSDN)来使用它们

请注意,内存不足异常和 StackOverflowException 可能不会被任何错误捕获捕获。

于 2008-12-14T17:26:04.337 回答
0

如果您只想捕获崩溃,则忽略所有错误并让 DrWatson 为您生成一个小型转储。然后你可以查看那个 ina 调试器(windbg 是 minidump 的首选),它会显示你的代码出错的行,以及所有参数、堆栈跟踪和寄存器。您可以将 Drwatson 设置为生成完整转储,您将在其中获取整个内存核心转储以进行调查。

我不建议在整个应用程序中使用 try/catch,除非您希望您的应用程序永远不会在用户面前“崩溃” - 它总是会被处理,并且可能会被忽略,因为您无能为力那一点。

不过,将 minidump 发送给您是另一回事,这里有一篇文章,您必须做一些工作才能通过 email/http/ftp/etc 发送它。

于 2008-12-14T20:12:21.770 回答
0

最好的方法是为 AppDomain.UnhandledExceptionApplication.ThreadException在你的应用程序的 main 函数中调用。这将允许您在应用程序中记录任何未处理的异常。在 try catch 块中包装 run 并不能捕获所有内容。

于 2008-12-14T17:57:58.530 回答