Предотвращение отбрасывания внешнего исключения при вызове из BeginInvoke

, у меня есть обработчик для 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 нижнего уровня.)

11
задан Joe White 19 December 2011 в 18:33
поделиться