Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何实施“一个”;捕捉';em all";恢复异常处理程序?_C#_Exception - Fatal编程技术网

C# 如何实施“一个”;捕捉';em all";恢复异常处理程序?

C# 如何实施“一个”;捕捉';em all";恢复异常处理程序?,c#,exception,C#,Exception,我想知道如何在应用程序级别编写一个捕获所有异常处理程序,让用户可以选择恢复应用程序流?这简直是一个糟糕的设计。不要对这样的事情使用异常。异常仅在程序员不希望发生的情况下使用 如果您想要错误处理。不要使用像这样的异常,rahter构建一个系统,在这个系统中,您可以保存状态并可以返回到状态等。。。但是使用异常来处理状态是个坏主意。这取决于你所说的“恢复”是什么意思。异常的问题在于,除非您非常小心,否则当异常发生时,您的应用程序状态很可能已损坏—您可能已经完成了半个操作 如果您可以隔离您的操作,就像数

我想知道如何在应用程序级别编写一个捕获所有异常处理程序,让用户可以选择恢复应用程序流?

这简直是一个糟糕的设计。不要对这样的事情使用异常。异常仅在程序员不希望发生的情况下使用


如果您想要错误处理。不要使用像这样的异常,rahter构建一个系统,在这个系统中,您可以保存状态并可以返回到状态等。。。但是使用异常来处理状态是个坏主意。

这取决于你所说的“恢复”是什么意思。异常的问题在于,除非您非常小心,否则当异常发生时,您的应用程序状态很可能已损坏—您可能已经完成了半个操作


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

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

我认为使用全局错误处理程序确实不可行。您需要弄清楚什么样的错误在应用程序中的不同点上是可恢复的,并编写特定的错误处理程序来解决出现的错误——除非您想求助于应用程序重新启动,这取决于实际的错误是什么。为了进行任何类型的恢复,您需要保存足够的状态,以便从已知的良好状态重新启动。

有一些示例说明了如何进行恢复

基本上,您可以通过以下方式围绕可能引发异常的代码:

try
{
  MyMethodThatMightThrow();
}
catch(Exception ex)
{
   bool rethrow = ExceptionPolicy.HandleException(ex, "SomePolicy");
   if (rethrow) throw;
}
然后,您可以将策略配置为向用户显示对话框,并询问用户是否要继续


您仍然需要在您认为处于一致状态的代码中放置try-catch块。

在某些版本的.NET中,您实际上可以在应用程序的.Run()周围放置一个catcher(您可以在program.cs中找到)这应该能捕捉到所有主线程的异常,但是在大多数情况下,这可能是糟糕的设计,不会给你太多“恢复”的机会。 此外,您将始终必须手动处理后台线程上的任何异常


您可以设计一个应用程序来“捕获所有内容”,并显示一条常见的错误消息和调试信息,只要您稍后退出就可以了。非常不鼓励的是向用户提供“简历”,因为从长远来看,这可能会给您带来更多的问题。

您应该仔细阅读与VB的“错误简历上的
下一步
”错误处理风格相关的所有问题。听起来你想为C#实现这一点

即使您可以从生成异常的位置恢复,这也是错误处理的一种失败技术。全局处理程序实际上无法处理任何错误/异常-它不可能知道任何任意情况需要什么

您必须设置某种全局变量,并让主线代码不断检查它是否有错误指示(即,使用VB技术)


我认为,要从您描述的错误中恢复,最好的方法是在应用程序级别捕获异常,记录问题,通知用户(并可能为您生成/发送某种类型的问题报告),然后重新启动应用程序。当然,如果您捕捉到更接近问题区域的异常,该处理程序有机会做一些更智能的事情,因此您不应该依赖应用程序级处理程序作为支柱,就像故障保护一样。

我假设您正在编写Windows应用程序,在这种情况下,,您可以这样做。我将把你是否应该这样做的对错留给别人。关于这一点,已经有足够多的答案,我建议您在实际操作之前仔细考虑这些答案

请注意,此代码在调试器中的行为与直接运行应用程序时的行为不同(可能是另一个不这样做的原因)。要使应用程序显示messagebox并在此后继续,您需要从资源管理器而不是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);
        }
    }
}
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");
        }

    }
}

(将button1添加到表单并将其附加到button1_单击。)

在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);
            }
        }
    }
}
使用系统;
使用System.Windows.Forms;
Net系统;
使用System.Net.Mail;
使用系统线程;
命名空间异常HandlerTest
{
静态类程序
{
/// 
///应用程序的主要入口点。
/// 
[状态线程]
静态void Main()
{
Application.ThreadException+=
新ThreadExceptionEventHandler(应用程序\u ThreadException);
//设计器生成的命令。
}
静态无效应用程序\u ThreadException(对象发送方,ThreadExceptionEventArgs e)
{
var fromAddress=新邮件地址(“您的Gmail地址”、“您的姓名”);
var toAddress=新邮件地址(“您希望接收报告的电子邮件地址”、“您的姓名”);
const string fromPassword=“您的密码”;
const string subject=“异常报告”;
异常=e.异常;
字符串正文=exception.Message+“\n”+exception.Data+“\n”+exception.StackTrace+“\n”+exception.Source;
var smtp=新SmtpClient
{
Host=“smtp.gmail.com”,
端口=587,
EnableSsl=true,