2015-05-19 33 views
1

建議的副本約爲DispatcherUnhandledException,而不是AppDomain.CurrentDomain.UnhandledException應該在哪裏訂閱AppDomain.UnhandledException?

原始

應該在哪裏AppDomain.UnhandledException進行訂閱?在MSDN的例子只是表明它在Main,這就是我在做的WinForms:我同意它Program.Main

AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; 

但在WPF,我無法找到一個合適的地方吧隱藏着Main。我已經搜索過了,但主要是找討論是否訂閱它,假設讀者現在會在哪裏。

+0

您可以在* app.xaml.cs *中執行此操作。請參閱:[未處理的例外] [1] [1]:http:// stackoverflow。com/questions/2251868 /未處理的異常 – musium

+0

@musium這隻適用於DispatcherUnhandledException。對於'AppDomain.UnhandledException',至少智能感知不顯示相同。 – ispiro

+0

這是WPF中最接近UnhandledException(Winforms)的東西。 請參閱:https://msdn.microsoft.com/en-us/library/system.windows.application.dispatcherunhandledexception%28v=vs.110%29.aspx – musium

回答

1

WPF中的Main()入口點是從App.xaml源文件自動生成的。儘早您必須訂閱該事件是在構造函數中App.xaml.cs App類:

public partial class App : Application { 
    public App() { 
     AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; 
    } 

    private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { 
     // etc... 
    } 
} 

然而,這不是「完美」,你無法探測出你的應用程序類的字段初始化任何故障。除了在您的應用程序類中使用的類型的任何JIT編譯失敗之外,缺少作爲常見麻煩製造者的組件或版本問題。

爲了避免遺漏這些,您需要放棄自動生成的代碼並編寫自己的Main()方法。假設您沒有大量修改app.xaml文件。從項目中刪除該文件,並添加一個新的類,我會建議Program.cs :)並使其看起來類似於:

using System; 
using System.Runtime.CompilerServices; 
using System.Windows; 

namespace WpfApplication1 { 
    class Program { 
     [STAThread] 
     public static void Main(string[] args) { 
      AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; 
      Start(); 
     } 

     [MethodImpl(MethodImplOptions.NoInlining)] 
     private static void Start() { 
      var app = new App(); 
      app.Run(new MainWindow()); 
     } 

     private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { 
      // etc.. 
     } 
    } 

    public class App : Application { 
     // etc.. 
    } 
} 
3

假設您在Visual Studio中使用默認模板創建項目,則應該有一個名爲app.xaml的文件,並在其下面有另一個名爲app.xaml.cs的文件。

裏面的App類,你可以在OnStartup開始(與Dispatcher.UnhandledException一起)添加:

protected override void OnStartup(StartupEventArgs e) 
{ 
    // don't forget to call base implementation 
    base.OnStartup(e); 

    Dispatcher.UnhandledException += Dispatcher_UnhandledException; 
    AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; 
} 

其實,Dispatcher.UnhandledException應該是在大多數情況下足夠了。這意味着您可以完全跳過AppDomain.CurrentDomain.UnhandledException。註冊到AppDomain.CurrentDomain.UnhandledException的唯一原因將是獲取除主UI線程以外的線程中引發的異常。但我認爲最好的做法是在各自的線索中實際捕捉這些例外情況。

+0

我在所需的'base'調用中編輯。 +1 btw –

+0

謝謝,但我也在編輯它。我會做不同的事情。 – Kryptos

+0

沒問題。繼續:) –

1

您可以在App.xaml.cs覆蓋OnStartup方法,這是你到了Main方法最接近的(或者,如果你會使用App constructor`)

public partial class App : Application 
{ 
    protected override void OnStartup(StartupEventArgs e) 
    { 
     base.OnStartup(e); 

     // register the event handler here 
     AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; 
    } 
} 

請注意,這需要你省略StartupUri並自己打開Window

+1

謝謝。是否有一個'基地'OnStartup我必須在那之後打電話或通常是空的? – ispiro

+0

是的,你應該叫它:http://referencesource.microsoft.com/#PresentationFramework/Framework/System/Windows/Application.cs,f2c567e5642bd030 –

+0

@xanatos:確實。從我複製的示例代碼中意外刪除了它。即使它現在什麼都不做,我通常會包括它。 –