我遇到的情况是,UI线程中抛出的异常不会在调用线程中捕获。
using System;
using System.Diagnostics;
using System.Threading;
using System.Windows;
namespace SynchronisationContextAndExceptionWPF
{
public partial class MainWindow : Window
{
private readonly SynchronizationContext _synchronizationContext;
public MainWindow()
{
InitializeComponent();
_synchronizationContext = SynchronizationContext.Current;
}
private void Button_OnClick(object sender, RoutedEventArgs e)
{
try
{
_synchronizationContext.Send(
x =>
{
try
{
DoSomethingOnUiThreadThatThrowsException();
}
catch (Exception)
{
Debug.WriteLine("Catched Exception in thread that threw it.");
throw;
}
}, null);
}
catch (Exception)
{
Debug.WriteLine("Catched Exception in thread that calles Send-Method.");
throw;
}
}
private static void DoSomethingOnUiThreadThatThrowsException()
{
throw new Exception("Any Exception...");
}
}
}首先,我认为这是不可能的(我找到的所有文档都说我可以捕获那里的异常)。经过一些研究,我发现了这个问题:我的应用程序使用了一个UnhandledExceptionHandler。它处理DispatcherUnhandledException-Event。我正在向用户显示一些信息并设置e.Handled = true;
using System.Diagnostics;
using System.Windows;
using System.Windows.Threading;
namespace SynchronisationContextAndExceptionWPF
{
public partial class App : Application
{
public App()
{
DispatcherUnhandledException += App_DispatcherUnhandledException;
}
private static void App_DispatcherUnhandledException(
object sender,
DispatcherUnhandledExceptionEventArgs e)
{
Debug.WriteLine("Catched Exception in UnhandledExceptionHandler.");
// This line makes the difference:
e.Handled = true;
}
}
}那么,问题是:即使我处理了,为什么DispatcherUnhandledException-Event也会被提出呢?你会如何解决这种情况?
发布于 2016-01-12 14:30:12
如果您有很多控件,则可以生成一个新的类,该类将处理特殊的异常变量。因此,您只需要更改_synchronizationContext的初始化(希望只在控件的基类中更改一次)。
public partial class MainWindow : Window
{
private readonly MySynchronizationContext _synchronizationContext;
public MainWindow()
{
InitializeComponent();
_synchronizationContext = new MySynchronizationContext(SynchronizationContext.Current);
}
private void button_Click(object sender, RoutedEventArgs e)
{
try
{
_synchronizationContext.Send(
x =>
{
DoSomethingOnUiThreadThatThrowsException();
}, null);
}
catch (Exception)
{
Debug.WriteLine("Catched Exception in thread that calles Send-Method.");
throw;
}
}
private static void DoSomethingOnUiThreadThatThrowsException()
{
throw new Exception("Any Exception...");
}
}
class MySynchronizationContext
{
SynchronizationContext innerContext;
public MySynchronizationContext(SynchronizationContext ctx)
{
innerContext = ctx;
}
public virtual void Send(SendOrPostCallback d, object state)
{
Exception threadException = null;
try
{
innerContext.Send(_ =>
{
try
{
d.Invoke(state);
}
catch (Exception exception)
{
threadException = exception;
}
}, null);
}
catch (Exception ex)
{
}
if (threadException != null)
{
throw new Exception("Synchronization error", threadException);
}
}
}发布于 2016-01-11 09:16:24
在lambda表达式中,您可以设置一个异常变量,然后在调用线程中检查该变量。如果设置了它,则在调用线程时抛出异常。
private void button_Click(object sender, RoutedEventArgs e)
{
Exception threadException = null;
try
{
_synchronizationContext.Send(
x =>
{
try
{
DoSomethingOnUiThreadThatThrowsException();
}
catch (Exception ex)
{
Debug.WriteLine("Catched Exception in thread that threw it.");
threadException = ex;
//throw; --> don't throw exception here; otherwise you will get DispatcherUnhandledException twice.
}
}, null);
}
catch (Exception)
{
Debug.WriteLine("Catched Exception in thread that calles Send-Method.");
throw;
}
if(threadException != null)
{
Debug.WriteLine("Catched Exception in thread that calles Send-Method.");
throw threadException; //throw you previously catched exception here.
}
}你好,丹尼尔
https://stackoverflow.com/questions/34715979
复制相似问题