, у меня есть обработчик для Application.ThreadException
, но я обнаружил, что исключения не всегда передаются в это правильно. В частности, если я генерирую исключение с внутренним исключением из обратного вызова BeginInvoke
, мой обработчик ThreadException
не получает исключение external - он только получает внутреннее исключение.
Пример кода:
public Form1()
{
InitializeComponent();
Application.ThreadException += (sender, e) =>
MessageBox.Show(e.Exception.ToString());
}
private void button1_Click(object sender, EventArgs e)
{
var inner = new Exception("Inner");
var outer = new Exception("Outer", inner);
//throw outer;
BeginInvoke(new Action(() => { throw outer; }));
}
Если я раскомментирую строку throw external;
и нажму кнопку, то в окне сообщения отобразится внешнее исключение (вместе с его внутренним исключением):
System.Exception: Внешний ---> System.Exception: Внутренний
--- Конец трассировки стека внутренних исключений ---
в WindowsFormsApplication1.Form1.button1_Click (отправитель объекта, EventArgs e) в C: \ svn \ trunk \ Code Base \ Source.NET \ WindowsFormsApplication1 \ Form1.cs: строка 55
в System.Windows.Forms.Control.OnClick (EventArgs e)
в System.Windows.Forms.Button.OnClick (EventArgs e)
в System.Windows.Forms.Button.OnMouseUp (событие MouseEventArgs)
в System.Windows.Forms.Control.WmMouseUp (сообщение & m, кнопка MouseButtons, щелчки Int32)
в System.Windows.Forms.Control.WndProc (сообщение & m)
в System.Windows.Forms.ButtonBase.WndProc (сообщение & m)
в System.Windows.Forms.Button.WndProc (Сообщение & m)
в System.Windows.Forms.Control.ControlNativeWindow.OnMessage (сообщение & m)
в System.Windows.Forms.Control.ControlNativeWindow.WndProc (сообщение & m)
в System.Windows.Forms.NativeWindow.Callback (IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
Но если выбрасывает внешний;
находится внутри вызова BeginInvoke
, как и в приведенном выше коде, тогда обработчик ThreadException
только получает внутреннее исключение. Внешнее исключение удаляется перед вызовом ThreadException
, и все, что я получаю, это:
System.Exception: Inner
(Здесь нет стека вызовов, потому что внутреннее
никогда не получалось В более реалистичном примере, где я поймал одно исключение и обернул его для повторной генерации, будет стек вызовов.)
То же самое произойдет, если я использую SynchronizationContext.Current.Post
вместо BeginInvoke
: внешнее исключение удаляется, а обработчик ThreadException
получает только внутреннее исключение.
Я попытался обернуть больше слоев исключений снаружи, на случай, если это просто удаляло самое внешнее исключение, но это не помогло: очевидно, где-то есть цикл, выполняющий что-то вроде while (e. InnerException! = Null) e = e.InnerException;
.
Я использую BeginInvoke
, потому что у меня есть код, который должен генерировать необработанное исключение для немедленной обработки с помощью ThreadException
, но этот код находится внутри ловушки Блок
выше по стеку вызовов (в частности, он находится внутри действия для Задачи
, а Задача
перехватит исключение и остановит его распространение). Я пытаюсь использовать BeginInvoke
, чтобы отложить выброс
до следующего раза, когда сообщения будут обработаны в цикле сообщений, когда меня больше не будет внутри этого улова
. Я не привязан к конкретному решению BeginInvoke
; Я просто хочу вызвать необработанное исключение.
Как я могу вызвать исключение - включая его внутреннее исключение - для достижения ThreadException
, даже когда я нахожусь внутри чужого catch
-all?
(Я могу Я не вызываю мой метод ThreadException
-handler напрямую из-за зависимостей сборки: обработчик перехватывается кодом запуска EXE, тогда как моя текущая проблема находится в DLL нижнего уровня.)