如何使用简历实现一个"catch'em all"异常处理程序?

30 c# exception

我想知道如何在应用程序级别编写catch'em所有异常处理程序,这将为用户提供恢复应用程序流的选项?

Vin*_*ghe 33

如果您正在运行Windows窗体应用程序:为Application.ThreadException事件添加处理程序.

  • 这个答案是对的.不知道为什么它被投票了.:-(也许人们正在贬低,因为他们认为不应该这样做.这一切都很好,但这确实回答了这个问题. (6认同)
  • @SamMeldrum因为这将*不*捕获所有异常.只有在UI线程中抛出的那些. (4认同)

Sam*_*rum 32

我假设您正在编写Windows应用程序,在这种情况下,是的,您可以这样做.我将把你是否应该对别人的权利和错误留下来.已经有足够的答案来看待这个,我建议你在实际做之前仔细考虑它们.

请注意,此代码在调试器中的行为与直接运行应用程序时的行为不同(另一个原因可能不是这样).要让应用程序显示消息框并在此后继续,您需要从资源管理器运行应用程序,而不是从visual studio运行.

创建一个新的Windows窗体应用程序.Program.cs中的代码如下所示:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Windows.Forms;

namespace WindowsFormsApplication2 {
    static class Program {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main() {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Form1 form1 = new Form1();
            Application.ThreadException += new ThreadExceptionEventHandler(form1.UnhandledThreadExceptionHandler);
            Application.Run(form1);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后使Form1中的代码看起来像这样:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace WindowsFormsApplication2 {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
        }

        public void UnhandledThreadExceptionHandler(object sender, ThreadExceptionEventArgs e) {
            this.HandleUnhandledException(e.Exception);
        }

        public void HandleUnhandledException(Exception e) {
            // do what you want here.
            if (MessageBox.Show("An unexpected error has occurred. Continue?",
                "My application", MessageBoxButtons.YesNo, MessageBoxIcon.Stop,
                MessageBoxDefaultButton.Button2) == DialogResult.No) {
                Application.Exit();
            }
        }

        private void button1_Click(object sender, EventArgs e) {
            throw new ApplicationException("Exception");
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

(将button1添加到表单并附加它button1_Click.)


Jon*_*eet 19

这取决于你对"简历"的意思.异常的问题在于,除非您非常小心,否则当异常发生时您的应用程序状态很可能已损坏 - 您可能已经完成了一半的操作.

如果您可以隔离操作 - 就像数据库隔离事务一样 - 那么您可以有效地让您的用户从"最后一个提交点"恢复.这在很大程度上取决于您的应用程序的类型.您能否提供有关您正在构建的应用程序类型的更多详细信息?

  • 只有Jon Skeet可以获得最多的赞成,并且要求提供更多信息; P (17认同)

Rav*_*tel 6

在program.cs类中使用以下代码.它会在发生异常时自动发送邮件.

using System;
using System.Windows.Forms;
using System.Net;
using System.Net.Mail;
using System.Threading; 

namespace ExceptionHandlerTest
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.ThreadException +=
                new ThreadExceptionEventHandler(Application_ThreadException);

            // Your designer generated commands.
        }

        static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) 
        {

            var fromAddress = new MailAddress("your Gmail address", "Your name");
            var toAddress = new MailAddress("email address where you want to receive reports", "Your name");
            const string fromPassword = "your password";
            const string subject = "exception report";
            Exception exception = e.Exception;
            string body = exception.Message + "\n" + exception.Data + "\n" + exception.StackTrace + "\n" + exception.Source;

            var smtp = new SmtpClient
            {
                Host = "smtp.gmail.com",
                Port = 587,
                EnableSsl = true,
                DeliveryMethod = SmtpDeliveryMethod.Network,
                UseDefaultCredentials = false,
                Credentials = new NetworkCredential(fromAddress.Address, fromPassword)
            };
            using (var message = new MailMessage(fromAddress, toAddress)
            {
                Subject = subject,
                Body = body
            })
            {
                //You can also use SendAsync method instead of Send so your application begin invoking instead of waiting for send mail to complete. SendAsync(MailMessage, Object) :- Sends the specified e-mail message to an SMTP server for delivery. This method does not block the calling thread and allows the caller to pass an object to the method that is invoked when the operation completes. 
                smtp.Send(message);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Fil*_*erg -2

这简直就是糟糕的设计。切勿对此类事情使用异常。异常仅在程序员不希望发生的情况下使用。

如果你想要错误处理。不要使用这样的异常,而是构建一个保存状态并可以返回状态等的系统...但是使用异常进行状态处理,是个坏主意。

  • 我认为这个问题根本不表明以不适当的方式使用异常。这只是“出了什么问题......好吧,让我们看看我们可以从哪里继续”。这似乎是一个非常自然的概念 - 只是很难稳健地实现,并且非常依赖于应用程序。 (3认同)
  • @Filip,你是对的;当我们使用 try..catch 时,我们应该具体说明我们想要/期望捕获的内容。帖子中提出的问题是,当我们遇到意外的异常时,我们想要记录它并优雅地处理它,而不是让 JIT 调试器吓到用户。 (3认同)