C# 如何使用简历实现一个“一网打尽”的异常处理程序?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/337702/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to implement one "catch'em all" exception handler with resume?
提问by
I wonder how can I write a catch'em allexception handler in the application level which will give the user the option to resume the application flow?
我想知道如何在应用程序级别编写一个catch'em all异常处理程序,让用户可以选择恢复应用程序流?
回答by Filip Ekberg
This just screams bad design all over. Never use exceptions for things like this. Exceptions are ONLY to be used when something the programmer did not intend to occures.
这只会尖叫糟糕的设计。永远不要对这样的事情使用异常。异常仅在程序员不打算发生的事情发生时使用。
If you want error-handling. dont use exceptions like this, rahter build a system where you save states and can go back to states etc... but using exceptions for state handling, bad idea.
如果你想要错误处理。不要使用这样的异常,rahter 构建了一个系统,您可以在其中保存状态并可以返回到状态等......但是使用异常进行状态处理,这是个坏主意。
回答by Jon Skeet
It depends on what you mean by "resume". The trouble with exceptions is that unless you're verycareful, by the time an exception happens your application state is quite possibly corrupt - you might have completed halfan operation.
这取决于你所说的“简历”是什么意思。异常的问题在于,除非您非常小心,否则当异常发生时,您的应用程序状态很可能已损坏——您可能已经完成了一半的操作。
If you can isolate your operations - much like a database isolates transactions - then you can effectively let your user resume from the "last commit point". That will very much depend on the type of your application though. Could you give us more details about the kind of application you're building?
如果你可以隔离你的操作——就像一个数据库隔离事务——那么你可以有效地让你的用户从“最后一次提交点”恢复。不过,这在很大程度上取决于您的应用程序类型。您能否为我们提供有关您正在构建的应用程序类型的更多详细信息?
回答by Vincent Van Den Berghe
If you are running a Windows Forms application: add a handler to the Application.ThreadException
event.
如果您正在运行 Windows 窗体应用程序:向Application.ThreadException
事件添加处理程序。
回答by tvanfosson
I don't think this is really feasible using a global error handler. You need to figure out what kind of errors are recoverable at different points in your application and write specific error handlers to address the errors as they occur -- unless you want to resort to application restart, which may or may not work depending on what the actual error is. In order to do any kind of resume, you'll need to save enough state to restart from a known good state.
我认为使用全局错误处理程序真的不可行。您需要弄清楚在应用程序的不同点可以恢复哪些类型的错误,并编写特定的错误处理程序来解决发生的错误——除非您想求助于应用程序重新启动,这可能会或可能不会起作用,具体取决于实际错误是。为了进行任何类型的恢复,您需要保存足够的状态以从已知的良好状态重新启动。
回答by Hallgrim
Microsoft Enterprise Library Exception Handling Application Blockhas examples of how you can do this.
Microsoft 企业库异常处理应用程序块提供了如何执行此操作的示例。
Basically you surround the code that can throw exceptions with this:
基本上你可以用这个包围可以抛出异常的代码:
try
{
MyMethodThatMightThrow();
}
catch(Exception ex)
{
bool rethrow = ExceptionPolicy.HandleException(ex, "SomePolicy");
if (rethrow) throw;
}
Then you can configure the Policy to show a dialog to the user and ask if she wants to continue.
然后您可以配置策略以向用户显示一个对话框并询问她是否要继续。
You still need to put try catch blocks around in your code at points where you believe you are at a consistent state.
您仍然需要将 try catch 块放在代码中您认为处于一致状态的位置。
回答by Quibblesome
In some versions of .NET you can actually put a catcher around the Application.Run() (you'll find this in program.cs) and this should catch all the Main Thread's exceptions however in most cases this maybe poor design and wont give you much of an opportunity to "resume". Additionally you will alwayshave to manually handle any exceptions on background threads.
在 .NET 的某些版本中,您实际上可以在 Application.Run() 周围放置一个捕手(您会在 program.cs 中找到它),这应该会捕获所有主线程的异常,但是在大多数情况下,这可能是糟糕的设计并且不会给出你有很大的机会“恢复”。此外,您将始终必须手动处理后台线程上的任何异常。
You can design an app to "catch all" and display a common error message and debug info, this is fine as long as you exit afterwards. What is highly discouraged is making a "resume" available to the user as this will probably give you more problems in the long-run.
您可以设计一个应用程序来“捕获所有”并显示常见的错误消息和调试信息,只要您之后退出就可以了。非常不鼓励向用户提供“简历”,因为从长远来看,这可能会给您带来更多问题。
回答by Michael Burr
You should read up on all the problems associated with VB's "On Error Resume Next
" style of error handling. It sounds like you're trying to implement this for C#.
您应该阅读与 VB 的“ On Error Resume Next
”错误处理风格相关的所有问题。听起来您正在尝试为 C# 实现这一点。
Even if you can resume from the point of where the exception is generated, this is a broken technique for error handling. There's no way for a global handler to actually be able to handle any error/exception - it can't possibly know what's required for any arbitrary situation.
即使您可以从产生异常的地方恢复,这也是一种错误处理技术。全局处理程序实际上无法处理任何错误/异常——它不可能知道任何情况下需要什么。
You would have to set some sort of global variable, and have the mainline code continually check it for error indications (ie., use the VB technique).
您必须设置某种全局变量,并让主线代码不断检查它是否有错误指示(即,使用 VB 技术)。
I think the best you can do to recover from an error like you're describing is to catch the exception at the application level, log the problem, inform the user (and potentially generate/send some sort of problem report for you), and restart the application. Of course, if you catch the exception closer to the problem area, that handler has a chance to do something a bit more intelligent, so you should not rely on the app-level handler as a crutch - just as a fail-safe.
我认为从您所描述的错误中恢复的最佳方法是在应用程序级别捕获异常,记录问题,通知用户(并可能为您生成/发送某种问题报告),以及重新启动应用程序。当然,如果您在靠近问题区域的地方捕获异常,则该处理程序有机会做一些更智能的事情,因此您不应该依赖应用程序级处理程序作为拐杖 - 就像故障安全一样。
回答by Sam Meldrum
I assume you are writing a Windows application in which case, yes, you can do this. I will leave the rights and wrongs of whether or not you should to others. There are already enough answers which look at this and I suggest you consider them carefully before you actually do this.
我假设您正在编写 Windows 应用程序,在这种情况下,是的,您可以这样做。你该不该我是非,我会留给别人。已经有足够的答案可以查看此内容,我建议您在实际执行此操作之前仔细考虑它们。
Note, that this code will behave differently in the debugger than it does if you run the application directly (another reason not to do it perhaps). To get the application to show the messagebox and to continue on thereafter you will need to run the application from explorer, not from visual studio.
请注意,此代码在调试器中的行为与直接运行应用程序时的行为不同(可能是不这样做的另一个原因)。要让应用程序显示消息框并在此之后继续,您需要从资源管理器而不是从 Visual Studio 运行应用程序。
Create a new Windows forms application. The code in Program.cs looks something like this:
创建一个新的 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);
}
}
}
Then make the code in Form1 look something like this:
然后使 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");
}
}
}
(Add button1 to the form and attach it button1_Click.)
(将 button1 添加到表单并将其附加 button1_Click。)
回答by Ravi Patel
Use below code in your program.cs class. It will automatically Send mail when exception occurs.
在您的 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);
}
}
}
}