Devrait utiliser les deux AppDomain.UnhandledException et de l'Application.DispatcherUnhandledException?
après avoir lu quelques excellents billets sur la différence entre AppDomain.UnhandledException et de l'Application.DispatcherUnhandledException, il semble que je dois être la manipulation à la fois. C'est parce qu'il est beaucoup plus probable que l'utilisateur peut récupérer d'une exception lancée par le thread principal D'UI (i.e., Application.DispatcherUnhandledException). - Il Correct?
aussi, devrais-je aussi donner à l'utilisateur une chance de continuer le programme pour les deux, ou juste le Application.DispatcherUnhandledException?
exemple de code ci-dessous traite les deux Appdomaines.UnhandledException et de l'Application.DispatcherUnhandledException, et à la fois donner à l'utilisateur la possibilité d'essayer de continuer en dépit de l'exception.
[merci et certains le code ci-dessous est levé à partir d'autres réponses]
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 [rédigé]
/// <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.nnError:{0}nnDo 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.nnError:{0}nnDo 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;
}
2 réponses
AppDomain.CurrentDomain.UnhandledException
en théorie capte toutes les exceptions sur tous les threads de l'appdomaine. J'ai trouvé ceci pour être très peu fiable.Application.Current.DispatcherUnhandledException
capture toutes les exceptions sur le thread. Cela semble fonctionner de manière fiable, et remplacera leAppDomain.CurrentDomain.UnhandledException
handler sur le thread UI (prend la priorité). Utiliseze.Handled = true
pour maintenir l'application en marche.pour attraper des exceptions sur d'autres threads (dans le meilleur des cas, ils sont manipulés sur leur propre thread), j'ai trouvé Système.Le filetage.Tâche.Tâche (seulement .NET 4.0 et au-dessus) à faible maintenance. Gérer les exceptions dans les tâches avec la méthode
.ContinueWith(...,TaskContinuationOptions.OnlyOnFaulted)
. Voir ma réponse ici pour plus de détails.
AppDomain.UnhandledException
gestionnaire est câblé comme:
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
mais je n'ai pas pu trouver un moyen de marquer comme manipulé dans le handler - donc cela semble toujours entraîner un arrêt de l'application peu importe ce que vous faites. Donc, je ne pense pas que ce est beaucoup de l'utilisation.
Mieux gérer Application.Current.DispatcherUnhandledException
et pour tester CommunicationObjectFaultedException
- comme vous pouvez vous en remettre en initialisant simplement votre proxy-exactement comme vous l'avez fait lors de la connexion initiale. 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();
}
où Initialize a votre initiale instanciation de procuration / code de connexion.
Dans le code que vous avez posté ci-dessus, je pense que vous êtes la manipulation DispatcherUnhandledException
deux fois - en câblant un handler en xaml et en code.