本文參考網上搜索的信息,並做了適當修改可以讓捕捉到異常之后阻止程序退出。
另給出了通過命令行自動重啟的方法。
如果一個線程里運行除以零的計算,如下面的代碼
private void button1_Click(object sender, EventArgs e) { System.Threading.Thread t = new System.Threading.Thread(() => { int a = 0; int c = 10 / a; }); t.Start(); }
將會導致程序自動結束,而且沒有任何提示信息 但是如果是在主線程里運行這個代碼,是會彈出異常信息對話框的
請問如何在線程里也出現這個異常信息對話框.或者
避免程序直接退出,忽略異常,繼續往下執行呢?
在WINFORM主線程捕獲全部異常就行,如下代碼:
//處理未捕獲的異常 Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); //處理UI線程異常 Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); //處理非UI線程異常 AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
最常出現的錯誤在 :UnhandledException 里出現。詳細代碼如下:
/// <summary> /// 應用程序的主入口點。 /// </summary> [STAThread] static void Main(string[] args) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); //處理未捕獲的異常 Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); //處理UI線程異常 Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); //處理非UI線程異常 AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); Application.Run(new Form1(args)); glExitApp = true;//標志應用程序可以退出 } /// <summary> /// 是否退出應用程序 /// </summary> static bool glExitApp = false; static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { LogHelper.Save("CurrentDomain_UnhandledException", LogType.Error); LogHelper.Save("IsTerminating : " + e.IsTerminating.ToString(), LogType.Error); LogHelper.Save(e.ExceptionObject.ToString()); while (true) {//循環處理,否則應用程序將會退出 if (glExitApp) {//標志應用程序可以退出,否則程序退出后,進程仍然在運行 LogHelper.Save("ExitApp"); return; } System.Threading.Thread.Sleep(2*1000); }; } static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e) { LogHelper.Save("Application_ThreadException:" + e.Exception.Message, LogType.Error); LogHelper.Save(e.Exception); //throw new NotImplementedException(); }

static class Program { private static log4net.ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); /// <summary> /// 是否退出應用程序 /// </summary> static bool glExitApp = false; /// <summary> /// 應用程序的主入口點。 /// </summary> [STAThread] static void Main() { _log.Info("程序啟動"); try { //處理未捕獲的異常 System.Windows.Forms.Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); System.Windows.Forms.Application.ThreadException += Application_ThreadException; AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new WebManager()); glExitApp = true; } catch (Exception ex) { _log.Error(ex); } _log.Info("程序關閉"); } private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { _log.Error("CurrentDomain_UnhandledException ==== IsTerminating : " + e.IsTerminating.ToString()); _log.Error("e.ExceptionObject : " + e.ExceptionObject); _log.Error(e); if (e.IsTerminating) { Common.Globalparams.ShowMessageDialog("系統發生錯誤,請聯系系統管理員,程序即將關閉。"); //循環處理,否則應用程序將會退出 if (glExitApp) { //標志應用程序可以退出,否則程序退出后,進程仍然在運行 _log.Error("====ExitApp"); return; } System.Threading.Thread.Sleep(2 * 1000); _log.Error("====UnhandledException While......"); Common.StartupHelper.CmdStartSelf(); } } private static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e) { var ex = e.Exception; if (ex != null) { _log.Error(ex); } } }
如果程序需要重啟只需要在捕獲的事件處理時啟動當前應用程序的代碼即可。參考如下:
CmdStartCTIProc(Application.ExecutablePath, "cmd params");//放到捕獲事件的處理代碼后,重啟程序,需要時加上重啟的參數 /// <summary> /// 在命令行窗口中執行 /// </summary> /// <param name="sExePath"></param> /// <param name="sArguments"></param> static void CmdStartCTIProc(string sExePath, string sArguments) { Process p = new Process(); p.StartInfo.FileName = "cmd.exe"; p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardInput = true; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.RedirectStandardError = true; p.StartInfo.CreateNoWindow = false; p.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; p.Start(); p.StandardInput.WriteLine(sExePath + " " + sArguments); p.StandardInput.WriteLine("exit"); p.Close(); System.Threading.Thread.Sleep(2000);//必須等待,否則重啟的程序還未啟動完成;根據情況調整等待時間 }
另外一種重啟進程的方式:
//重啟程序,需要時加上重啟的參數 System.Diagnostics.ProcessStartInfo cp = new System.Diagnostics.ProcessStartInfo(); cp.FileName = Application.ExecutablePath; cp.Arguments = "cmd params"; cp.UseShellExecute = true; System.Diagnostics.Process.Start(cp);
完整代碼:

public class StartupHelper { /// <summary> /// 在命令行窗口中執行指定程序。(可以包括程序本身) /// </summary> /// <param name="exePath"></param> /// <param name="sArguments"></param> public static void CmdStartApp(string exePath, string sArguments) { System.Diagnostics.Process p = new System.Diagnostics.Process(); p.StartInfo.FileName = "cmd.exe"; p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardInput = true; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.RedirectStandardError = true; p.StartInfo.CreateNoWindow = false; p.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; p.Start(); p.StandardInput.WriteLine(exePath + " " + sArguments); p.StandardInput.WriteLine("exit"); p.Close(); System.Threading.Thread.Sleep(2000);//必須等待,否則重啟的程序還未啟動完成;根據情況調整等待時間 } /// <summary> /// 啟動程序自己(一般程序異常退出時調用) /// </summary> /// <param name="strArguments"></param> public static void CmdStartSelf(string strArguments = "") { //重啟程序,需要時加上重啟的參數 System.Diagnostics.ProcessStartInfo cp = new System.Diagnostics.ProcessStartInfo(); cp.FileName = System.Windows.Forms.Application.ExecutablePath; cp.Arguments = strArguments; cp.UseShellExecute = true; System.Diagnostics.Process.Start(cp); } }
看了覺得有用的朋友,如果您方便的話,可以頂一下。謝謝!
出處:https://www.cnblogs.com/zaspring/archive/2013/04/16/3023927.html