27

AppDomain.UnhandledException और अनुप्रयोग के बीच अंतर के बारे में कुछ उत्कृष्ट पोस्ट पढ़ने के बाद। डिस्पैचर अननहेल्ड अपवाद, ऐसा प्रतीत होता है कि मुझे दोनों को संभालना चाहिए। ऐसा इसलिए है क्योंकि उपयोगकर्ता मुख्य यूआई थ्रेड (यानी, आवेदन। डिस्पैचर अननहेल्ड एक्सेप्शन) द्वारा फेंक दिए गए अपवाद से पुनर्प्राप्त कर सकता है। सही बात?दोनों AppDomain.UnhandledException और अनुप्रयोग का उपयोग करना चाहिए। डिस्पैचर UnnhandledException?

साथ ही, क्या मुझे उपयोगकर्ता को दोनों के लिए कार्यक्रम जारी रखने का मौका भी देना चाहिए, या सिर्फ आवेदन। डिस्पैचर अननहेल्ड अपवाद?

नीचे दिए गए उदाहरण कोड AppDomain.UnhandledException और Application.DispatcherUnhandledException दोनों को संभालता है, और दोनों उपयोगकर्ता को अपवाद के बावजूद जारी रखने का प्रयास करने का विकल्प देते हैं।

[धन्यवाद और नीचे दिए गए कोड के कुछ अन्य उत्तर से उठाया है]

App.xaml

<Application x:Class="MyProgram.App" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Startup="App_StartupUriEventHandler" 
     Exit="App_ExitEventHandler" 
     DispatcherUnhandledException="AppUI_DispatcherUnhandledException"> 
    <Application.Resources> 
    </Application.Resources> 
</Application> 

App.xaml.cs [संशोधित]

/// <summary> 
/// Add dispatcher for Appdomain.UnhandledException 
/// </summary> 
public App() 
    : base() 
{ 
    this.Dispatcher.UnhandledException += OnDispatcherUnhandledException; 
} 

/// <summary> 
/// Catch unhandled exceptions thrown on the main UI thread and allow 
/// option for user to continue program. 
/// The OnDispatcherUnhandledException method below for AppDomain.UnhandledException will handle all other exceptions thrown by any thread. 
/// </summary> 
void AppUI_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e) 
{ 
    if (e.Exception == null) 
    { 
     Application.Current.Shutdown(); 
     return; 
    } 
    string errorMessage = string.Format("An application error occurred. If this error occurs again there seems to be a serious bug 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); 
    //insert code to log exception here 
    if (MessageBox.Show(errorMessage, "Application User Interface 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(); 
     } 
    } 
    e.Handled = true; 
} 

/// <summary> 
/// Catch unhandled exceptions not thrown by the main UI thread. 
/// The above AppUI_DispatcherUnhandledException method for DispatcherUnhandledException will only handle exceptions thrown by the main UI thread. 
/// Unhandled exceptions caught by this method typically terminate the runtime. 
/// </summary> 
void OnDispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e) 
{ 
    string errorMessage = string.Format("An application error occurred. If this error occurs again there seems to be a serious bug 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); 
    //insert code to log exception here 
    if (MessageBox.Show(errorMessage, "Application UnhandledException 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(); 
     } 
    } 
    e.Handled = true; 
} 

उत्तर

31
  • सिद्धांत में AppDomain.CurrentDomain.UnhandledException appdomain के सभी धागे पर सभी अपवादों को पकड़ता है। e.Handled के बजाय, यदि आप प्रक्रिया को समाप्त नहीं करना चाहते हैं तो e.SetObserved() का उपयोग करें। हालांकि, मुझे यह बहुत अविश्वसनीय लगता है, हालांकि।

  • Application.Current.DispatcherUnhandledException यूआई थ्रेड पर सभी अपवादों को पकड़ता है। यह विश्वसनीय रूप से काम करता प्रतीत होता है, और यूआई थ्रेड पर AppDomain.CurrentDomain.UnhandledException हैंडलर को प्रतिस्थापित करेगा (प्राथमिकता लेता है)। एप्लिकेशन को चालू रखने के लिए e.Handled = true का उपयोग करें।

  • अन्य थ्रेड पर अपवाद को पकड़ने (सबसे अच्छा मामले में, वे अपने स्वयं के धागे पर नियंत्रित किया जाता है) के लिए, मैं कम रखरखाव होने के लिए System.Threading.Tasks.Task (4.0 केवल .NET और ऊपर) पाया। विधि .ContinueWith(...,TaskContinuationOptions.OnlyOnFaulted) के साथ कार्यों में अपवादों को संभाल लें। विवरण के लिए मेरा उत्तर here देखें।

+4

'AppDomain.CurrentDomain.UnhandledException 'को संभालने पर कोई' e.SetObserved() 'नहीं है। आप इसे 'TaskScheduler.UnobservedTaskException' के तर्कों से भ्रमित कर रहे हैं। – Hannobo

4

एक AppDomain.UnhandledException हैंडलर के रूप में वायर्ड किया गया है:

AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; 

लेकिन मुझे हैंडलर में संभालने के रूप में ध्वजांकित करने का कोई तरीका नहीं मिला - इसलिए ऐसा लगता है कि आप हमेशा क्या करते हैं, इससे कोई फर्क नहीं पड़ता कि आप क्या करते हैं। इसलिए मुझे नहीं लगता कि यह बहुत उपयोग है।

Application.Current.DispatcherUnhandledException को संभालने के लिए बेहतर और CommunicationObjectFaultedException के लिए परीक्षण करने के लिए - जैसा कि आप अपने प्रॉक्सी को फिर से शुरू करने से ठीक कर सकते हैं - ठीक उसी तरह जैसे आपने प्रारंभिक कनेक्शन में किया था। E.g:

void Current_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e) { 
    if (e.Exception is CommunicationObjectFaultedException) { //|| e.Exception is InvalidOperationException) { 
     Reconnect(); 
     e.Handled = true; 
    } 
    else { 
     MessageBox.Show(string.Format("An unexpected error has occured:\n{0}.\nThe application will close.", e.Exception)); 
     Application.Current.Shutdown(); 
    } 
} 

public bool Reconnect() { 
    bool ok = false; 
    MessageBoxResult result = MessageBox.Show("The connection to the server has been lost. Try to reconnect?", "Connection lost", MessageBoxButton.YesNo); 
    if (result == MessageBoxResult.Yes) 
     ok = Initialize(); 
    if (!ok) 
     Application.Current.Shutdown(); 
} 

जहां आरंभिक प्रारंभिक प्रॉक्सी तत्काल/कनेक्शन कोड है।

कोड आप मैं ऊपर पोस्ट में संदेह है कि आप DispatcherUnhandledExceptionसंभाल रहे हैं दो बार - XAML में और कोड में कोई हैंडलर तारों से।

+0

मुझे यह भी सुनिश्चित नहीं है कि यूआई थ्रेड के लिए अपवाद सौंपने की संभावना है या नहीं, लेकिन मुझे संदेह है कि ऐसा हो सकता है। यही कारण है कि दोनों के पास अंत में e.handled = सत्य है - इसे दो बार संभालने से रोकना चाहिए। – Kyle

संबंधित मुद्दे