【发布时间】:2016-06-23 16:39:04
【问题描述】:
如果对 Elasticsearch 的任何请求失败,我想显示一条道歉消息并关闭我的 WPF 应用程序。应用程序中有很多请求,所以我认为最方便的方法是在出现问题时在 OnRequestCompleted 回调中抛出异常,然后全局处理。但是,here 列出的 4 种处理未处理异常的方法中的每一种都不执行任何操作,应用程序只会崩溃。这是最简单的例子。有什么问题?
App.xaml
<Application x:Class="WPF_Elasticsearch_2._3.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
DispatcherUnhandledException="App_OnDispatcherUnhandledException"
StartupUri="MainWindow.xaml">
</Application>
App.xaml.cs
using System;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;
using Nest;
namespace WPF_Elasticsearch_2._3
{
public partial class App : Application
{
public static IElasticClient ElasticClient { get; private set; }
public App()
{
AppDomain.CurrentDomain.UnhandledException += App_OnUnhandledException;
TaskScheduler.UnobservedTaskException += App_OnUnobservedTaskException;
Dispatcher.UnhandledException += App_OnDispatcherUnhandledException;
var connectionSettings = new ConnectionSettings(new Uri("http://localhost:9200"))
.OnRequestCompleted(callDetails =>
{
if (!callDetails.Success)
throw new Exception("Unsuccessful request!");
});
ElasticClient = new ElasticClient(connectionSettings);
}
private void App_OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
MessageBox.Show(e.Exception.Message);
e.Handled = true;
Shutdown(-1);
}
private void App_OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
MessageBox.Show(((Exception)e.ExceptionObject).Message);
Shutdown(-1);
}
private void App_OnUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
{
MessageBox.Show(e.Exception.Message);
e.SetObserved();
Shutdown(-1);
}
}
}
MainWindow.xaml
<Window x:Class="WPF_Elasticsearch_2._3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="240" Width="320">
<Button Click="ButtonBase_OnClick">Make request</Button>
</Window>
MainWindow.xaml.cs
using System.Windows;
namespace WPF_Elasticsearch_2._3
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
App.ElasticClient.Search<object>(descriptor => descriptor
.Index("test-index")
.Type("test-type"));
}
}
}
【问题讨论】:
-
你使用不同的appDomains吗?您是否尝试将 OnRequestCompleted 的 EventHandler 代码移动到“真实方法”而不是使用匿名?您可能需要调用?
-
我不会真正关注你链接的那个帖子。如果您要抛出自己的异常,您仍然需要在某个地方处理它,否则它将使应用程序崩溃。在这方面,要获得您想要的行为,您可能不需要 抛出异常,您只需在抛出异常的地方产生您想要的行为。通常,要处理异常,您需要使用
try/catch块 -
@pay 一些令人讨厌但重要的问题由此而来: - 未处理的异常事件的概念是什么,以及如何使它工作? - 我应该在哪里放置 try/catch 块才能处理所有异常?与 WPF 不同,控制台和 WinForms 应用程序具有易于理解的 Main 方法。我不会仅仅产生一些行为,因为该应用程序具有复杂的结构,并且当第一条消息出现在屏幕上时可能会出现其他有关错误的消息,并且我需要停止所有发生的错误。
-
@Mat 我自己没有创建任何 AppDomain,这里提供的文件是我更改默认生成代码的唯一文件。将回调方法传递给 App 类并将其作为参数传递给 OnRequestCompleted 没有帮助。
-
我不会说未处理的异常是 for 任何东西,异常本身是出于某种原因,但它只是“未处理”,因为程序员没有处理它。您可以拥有任意数量的 try/catch 块,正如您所说,“我应该将 try/catch 块放在哪里才能处理所有异常?” - 答案就在您需要它们的任何地方。
标签: c# wpf exception-handling nest unhandled