c# label - WPF全局異常處理程序




textblock error (9)

最佳答案可能是https://stackoverflow.com/a/1472562/601990 。

這裡有一些代碼展示瞭如何使用它:

App.xaml.cs

public sealed partial class App
{
    protected override void OnStartup(StartupEventArgs e)
    {
        // setting up the Dependency Injection container
        var resolver = ResolverFactory.Get();

        // getting the ILogger or ILog interface
        var logger = resolver.Resolve<ILogger>();
        RegisterGlobalExceptionHandling(logger);

        // Bootstrapping Dependency Injection 
        // injects ViewModel into MainWindow.xaml
        // remember to remove the StartupUri attribute in App.xaml
        var mainWindow = resolver.Resolve<Pages.MainWindow>();
        mainWindow.Show();
    }

    private void RegisterGlobalExceptionHandling(ILogger log)
    {
        // this is the line you really want 
        AppDomain.CurrentDomain.UnhandledException += 
            (sender, args) => CurrentDomainOnUnhandledException(args, log);

        // optional: hooking up some more handlers
        // remember that you need to hook up additional handlers when 
        // logging from other dispatchers, shedulers, or applications

        Application.Dispatcher.UnhandledException += 
            (sender, args) => DispatcherOnUnhandledException(args, log);

        Application.Current.DispatcherUnhandledException +=
            (sender, args) => CurrentOnDispatcherUnhandledException(args, log);

        TaskScheduler.UnobservedTaskException += 
            (sender, args) => TaskSchedulerOnUnobservedTaskException(args, log);
    }

    private static void TaskSchedulerOnUnobservedTaskException(UnobservedTaskExceptionEventArgs args, ILogger log)
    {
        log.Error(args.Exception, args.Exception.Message);
        args.SetObserved();
    }

    private static void CurrentOnDispatcherUnhandledException(DispatcherUnhandledExceptionEventArgs args, ILogger log)
    {
        log.Error(args.Exception, args.Exception.Message);
        // args.Handled = true;
    }

    private static void DispatcherOnUnhandledException(DispatcherUnhandledExceptionEventArgs args, ILogger log)
    {
        log.Error(args.Exception, args.Exception.Message);
        // args.Handled = true;
    }

    private static void CurrentDomainOnUnhandledException(UnhandledExceptionEventArgs args, ILogger log)
    {
        var exception = args.ExceptionObject as Exception;
        var terminatingMessage = args.IsTerminating ? " The application is terminating." : string.Empty;
        var exceptionMessage = exception?.Message ?? "An unmanaged exception occured.";
        var message = string.Concat(exceptionMessage, terminatingMessage);
        log.Error(exception, message);
    }
}

這個問題在這裡已經有了答案:

有時,在不可重現的情況下,我的WPF應用程序崩潰而沒有任何消息。 該應用程序只需立即關閉。

哪裡是實施全球Try / Catch區塊的最佳地點。 至少我必須實現一個消息框:“對不便帶來的不便...”


Application.Dispatcher.UnhandledException的代碼的一個簡單示例:

    public App() :base() {
        this.Dispatcher.UnhandledException += OnDispatcherUnhandledException;
    }

    void OnDispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e) {
        string errorMessage = string.Format("An unhandled exception occurred: {0}", e.Exception.Message);
        MessageBox.Show(errorMessage, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
        e.Handled = true;
    }

我在App.xaml.cs中添加了這段代碼


正如剛才提到的

Application.Current.DispatcherUnhandledException將不會捕獲從另一個線程,然後是主線程拋出的異常。

這實際上取決於線程的創建方式

一個不由Application.Current.DispatcherUnhandledException處理的情況是System.Windows.Forms.Timer,如果您在除主線程之外的其他線程上運行Forms,則可以使用Application.ThreadException來處理這些情況,您將需要設置Application.ThreadException來自每個這樣的線程


您可以在不同級別捕獲未處理的異常:

  1. AppDomain.UnhandledException所有線程。
  2. Dispatcher.UnhandledException從一個特定的UI調度程序線程。
  3. Application.DispatcherUnhandledException從您的WPF應用程序中的 UI調度程序線程。
  4. 每個使用任務調度程序進行異步操作的AppDomain中的TaskScheduler.UnobservedTaskException

您應該考慮在什麼級別捕捉未處理的異常。

決定#2和#3取決於您是否使用多個WPF線程。 這是一個非常異乎尋常的情況,如果你不確定你是不是,那很可能你不是。



我在我的WPF應用程序中使用以下代碼,在發生未處理的異常時顯示“對不便之處”對話框。 它顯示異常消息,並詢問用戶是否要關閉應用程序或忽略異常並繼續(當發生非致命異常並且用戶仍然可以正常繼續使用該應用程序時,後一種情況很方便)。

在App.xaml中添加啟動事件處理程序:

<Application .... Startup="Application_Startup">

在App.xaml.cs代碼中,添加將註冊全局應用程序事件處理程序的Startup事件處理程序函數:

using System.Windows.Threading;

private void Application_Startup(object sender, StartupEventArgs e)
{
    // Global exception handling  
    Application.Current.DispatcherUnhandledException += new DispatcherUnhandledExceptionEventHandler(AppDispatcherUnhandledException);    
}

void AppDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{    
    \#if DEBUG   // In debug mode do not custom-handle the exception, let Visual Studio handle it

    e.Handled = false;

    \#else

    ShowUnhandledException(e);    

    \#endif     
}

void ShowUnhandledException(DispatcherUnhandledExceptionEventArgs e)
{
    e.Handled = true;

    string errorMessage = string.Format("An application error occurred.\nPlease check whether your data is correct and repeat the action. If this error occurs again there seems to be a more serious malfunction in the application, and you better close it.\n\nError: {0}\n\nDo you want to continue?\n(if you click Yes you will continue with your work, if you click No the application will close)",

    e.Exception.Message + (e.Exception.InnerException != null ? "\n" + 
    e.Exception.InnerException.Message : null));

    if (MessageBox.Show(errorMessage, "Application Error", MessageBoxButton.YesNoCancel, MessageBoxImage.Error) == MessageBoxResult.No)   {
        if (MessageBox.Show("WARNING: The application will close. Any changes will not be saved!\nDo you really want to close it?", "Close the application!", MessageBoxButton.YesNoCancel, MessageBoxImage.Warning) == MessageBoxResult.Yes)
    {
        Application.Current.Shutdown();
    } 
}

完整的解決方案在here

它的示例代碼非常好。 但是,請注意它不會關閉應用程序。添加行Application.Current.Shutdown(); 優雅地關閉應用程序。


除了上面的帖子:

Application.Current.DispatcherUnhandledException

將不會捕獲從另一個線程,然後是主線程拋出的異常。 你必須在其實際的線程上處理這些異常。 但是如果你想在你的全局異常處理器上處理它們,你可以將它傳遞給主線程:

 System.Threading.Thread t = new System.Threading.Thread(() =>
    {
        try
        {
            ...
            //this exception will not be catched by 
            //Application.DispatcherUnhandledException
            throw new Exception("huh..");
            ...
        }
        catch (Exception ex)
        {
            //But we can handle it in the throwing thread
            //and pass it to the main thread wehre Application.
            //DispatcherUnhandledException can handle it
            System.Windows.Application.Current.Dispatcher.Invoke(
                System.Windows.Threading.DispatcherPriority.Normal,
                new Action<Exception>((exc) =>
                    {
                      throw new Exception("Exception from another Thread", exc);
                    }), ex);
        }
    });

其中一種方法是..

try:
   You do your operations here;
   ......................
except(Exception1[, Exception2[,...ExceptionN]]]):
   If there is any exception from the given exception list, 
   then execute this block.
   ......................
else:
   If there is no exception then execute this block. 

另一種方法是創建執行由except塊執行的任務的方法,並通過你寫的所有except塊調用它。

try:
   You do your operations here;
   ......................
except Exception1:
    functionname(parameterList)
except Exception2:
    functionname(parameterList)
except Exception3:
    functionname(parameterList)
else:
   If there is no exception then execute this block. 

def functionname( parameters ):
   //your task..
   return [expression]

我知道第二個不是最好的方法,但我只是展示了做這件事的方法。







c# .net wpf exception exception-handling