在我的WPF应用程序中吞下了异常。如何强制应用程序崩溃?

时间:2010-01-31 12:03:51

标签: wpf mvvm exception-handling

我是WPF新手,我使用的是VS2010 beta2,.NET 4.0。

我的代码中的

Throw new Exception("test")只是吞下异常而应用程序不会崩溃。

这不是我所期望的,如果发生未处理的异常,我希望应用程序崩溃。

有没有一种简单的方法可以达到这个目的?

此外,Application.DispatcherUnhandledExceptionAppDomain.UnhandledException都未执行。这可能是因为所有代码都是作为数据绑定的一部分执行的(我使用MVVM模式并在ViewModel构造函数中抛出异常)。

调试时,我可以查看“输出”窗口,找出问题所在。但在我看来奇怪的是,该应用程序只是忽略错误,使UI处于不正确状态并且不会崩溃。

修改

似乎在数据绑定时可能只发生非关键的绑定异常。也许解决方案可能是从绑定执行中提取与绑定没有直接关系的功能(例如连接到数据库)。但是我不确定如何在MVVM中实现它。

简化示例:

XAML:

<DataTemplate DataType="{x:Type vm:ItemViewModel}">
    <vw:ItemControl />
</DataTemplate>

<ContentControl 
 Content="{Binding Path=MyItem}"     
 />  

其中MyItem创建并返回ItemViewModel的实例。问题是ItemViewModel的构造函数是作为数据绑定的一部分执行的,我不确定这是不是很好的做法(这个构造函数包含可能失败的代码 - 例如,如果数据库不可访问)。

5 个答案:

答案 0 :(得分:1)

您可以捕获绑定期间引发的异常并重新抛出它们 - 请参阅the answer to this question

答案 1 :(得分:0)

为什么会回答herehere。他们还解释了更好地调试异常的方法。但是没有关于如何将它们变成未处理的异常的答案。

编辑:您可以指示绑定在绑定更新源时发出错误信号。见here。然后,您可以使用ErrorTemplate(或使用默认值)在UI中显示错误。

{Binding Age, ValidatesOnDataErrors=true}

答案 2 :(得分:0)

我会自己回答我的问题:

通过将可能失败的代码(例如数据库访问调用)从(数据绑定)属性getter移动到View-Model的构造函数,我实现了正确的行为。另外我使用BackgroundWorker进行此调用,因此代码是异步执行的。我在RunWorkerCompleted中重新抛出可能的异常 - BackgroundWorker保证它将在UI线程上完成。

public TestViewModel()
{  
    BackgroundWorker bckgWorker = new BackgroundWorker();
    bckgWorker.DoWork += ((s, e) => this.TestExecuteCode());            
    bckgWorker.RunWorkerCompleted += ((s, e) => 
    { 
        if (e.Error != null) 
            throw e.Error; 
    });

    bckgWorker.RunWorkerAsync();
}

private void TestExecuteCode()
{
    this.DataBoundProperty = LoadDataFromDb();
}

我非常喜欢这种异步获取数据的方法,而不是在XAML中的Binding上设置IsAsync = true。与IsAsync方法相比,当渲染线程抛出异常并且默认情况下被吞下时,此方法永远不会吞下Exceptions。

警告:在单元测试中运行此代码时,默认情况下不会将RunWorkerCompleted事件处理程序封送回调用方的线程。必须手动设置BackgroundWorker使用的SynchronizationContext,以便正确处理单元测试中的异常。

答案 3 :(得分:0)

.Net 4.0 \ WPF介绍了这样做的方法,请参阅answer here

答案 4 :(得分:-1)

我很确定使用.NET 4的设计不佳的应用程序可能会滥用AppDomain.FirstChanceException来实现此目的。

构建日志为您提供了在WPF应用程序中查找问题所需了解的所有内容。这是我在某些代码中抛出NotImplementedException时记录的内容,我知道UI必然会被绑定:

System.Windows.Data Error: 17 : Cannot get 'ExitCommand' value (type 'RelayCommand') from '' (type 'ControlCenter'). BindingExpression:Path=ExitCommand; DataItem='ControlCenter' (Name='controlCenterWindow'); target element is 'MenuItem' (Name=''); target property is 'Command' (type 'ICommand') TargetInvocationException:'System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NotImplementedException: The method or operation is not implemented.
   at Tvl.Client.ControlCenter.get_ExitCommand() in C:\dev\Tvl\Client\ControlCenter.xaml.cs:line 25
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle._InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeType typeOwner)
   at System.RuntimeMethodHandle.InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeType typeOwner)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, Object[] index)
   at MS.Internal.Data.PropertyPathWorker.GetValue(Object item, Int32 level)
   at MS.Internal.Data.PropertyPathWorker.RawValue(Int32 k)'