Oto mój hipotetyczny przykład. Mam bardzo proste okno WPF z jednym przyciskiem. Zdarzenie Button.Click ma moduł obsługi, który działa w ten sposób.Dlaczego wyjątki nie są propagowane przez program rozsyłający WPF Dispatcher.Invoke?
Action doit =() =>
{
Action error =() => { throw new InvalidOperationException("test"); };
try {
this.Dispatcher.Invoke(error, DispatcherPriority.Normal);
} catch (Exception ex) {
System.Diagnostics.Trace.WriteLine(ex);
throw;
}
};
doit.BeginInvoke(null, null);
Spodziewam się, że wyjątek zostanie złapany i spisane przez wywołanie Trace.WriteLine
. Zamiast tego nie zostanie przechwycony żaden wyjątek, a aplikacja zostanie zerwana.
Czy ktoś wie o możliwym wytłumaczeniu, dlaczego tak się dzieje? A jakie obejście proponujesz, aby wychwycić wyjątki zgłoszone przez delegata, na który powołuje się Dispatcher.Invoke
?
Aktualizacja 1: Wpisuję kod throw
w kod obsługi wyjątku. Nie chcę zignorować wyjątku. Chodzi mi o to, aby właściwie się nim posługiwać. Problem polega na tym, że kod obsługi wyjątku nigdy nie jest wykonywany.
Pamiętaj, że jest to przykład hipotetyczny. Mój prawdziwy kod nie wygląda tak. Załóżmy również, że nie mogę zmienić kodu w metodzie, która ma zostać wywołana.
Aktualizacja 2: Rozważ ten podobny przykład. Zamiast okna WPF mam okno Windows Forms. Ma przycisk z prawie dokładnie taką samą obsługą. Jedyną różnicą jest kod wywołania. Tak to wygląda.
this.Invoke(error);
W Windows Forms wykonywany jest kod obsługi wyjątków. Dlaczego różnica?
Sposób, w jaki radzę sobie z wychwyconymi wyjątkami, jest nieistotny. Mógłbym umieścić trochę logowania lub cokolwiek tam. Problem polega na tym, że kod obsługi wyjątku nigdy nie jest wykonywany. – jpbochi
Dzieje się tak dlatego, że wyjątek jest zgłaszany w innym wątku - wątku 'Dispatcher'. –
@Sthepen: Wiem o tym. Spodziewałem się uzyskać wyjątek TargetInvocationException lub coś podobnego. – jpbochi