简体   繁体   中英

Throw Exception On UI Thread

I have an eventhandler that gives me an exception as an argument. I would like to throw that argument on the UI thread. It seems this sometimes does not throw the exception on the UI thread, any idea why?

             _dispatcher = Application.Current.Dispatcher

            if (_dispatcher != null && !_dispatcher.CheckAccess())
            {
                _dispatcher.BeginInvoke((ThreadStart)delegate
                {
                    throw args.Exception;
                }, DispatcherPriority.Normal);
                return;
            }

Your question is quite vague but it looks like a problem I faced recently. For some reasons, when I catched an exception from a worker thread and tried to rethrow it to the UI thread, the exception was not handled (despite a hight level error management with subsctition the DispatcherUnhandledException event) and my app crashed.

Here is my original code

try
{
    action(); // Perform task from worker thread
}
catch (Exception ex)
{
    var stackBeforDispatch = ex.StackTrace;//get the stack trace before it is dispatched to keep track of the original error origin
    var uiThread = Application.Current != null ? Application.Current.Dispatcher : Dispatcher.CurrentDispatcher;//try to find the ui dispatcher if any
    Action action1 = action;
    //dispatch to ui thread so that the information goes up to the user
    uiThread.Invoke(new Action(() =>
    {
        ex.Source = ex.Source += string.Format("{0}From Thread: {0}   {1}{0}From Method: {0}   {2}{0}Stack trace before Dispatch: {0}   {3}",
            Environment.NewLine,
            _dispatcherThread.Name,
            action1.Method.Name,
            stackBeforDispatch);
        throw ex;

    }));
}

Changing the dispatcher priority to a lower priority, for me DispatcherPriority.SystemIdle , seems to solve the problem : now, all my exception that occur in a background thread are properly re thrown to the UI thread where they are handled by the DispatcherUnhandledException .

Actually, I dont' understand WHY, and I found your question searching for an explanation to that :)

I'm not sure where or how you are handling this event, but is it possible that sometimes you are already on the UI thread? In that case, you're missing the other half.

if (_dispatcher != null)
{
    if (!_dispatcher.CheckAccess())
    {
        //invoke as above
    }
    else
    {
        throw args.Exception;
    }
}

Edit: That said, I agree with Hans. If you dispatch an exception to the UI thread, who will catch it?

It seems this sometimes does not throw the exception on the UI thread, any idea why?

Because of this:

if (_dispatcher != null && !_dispatcher.CheckAccess())

You don't need to CheckAccess().

This question is old; nonetheless, a similar issue now plagues my UWP app. Occasionally I must unwind the call stack by allowing an exception to propagate up it. I need the exception to reach the app's UnhandledException handler, but that wasn't always happening. This issue included the obvious case of throwing on a non-UI thread. It also included a non-obvious case, the causality of which I have yet to pin down, of throwing on the UI thread.

I conjured up the below solution. I catch the exception and then explicitly post it to the synchronization context. Due to the strange aforementioned issue, I must do this even while already running on the current synchronization context . Otherwise, the exception sometimes doesn't reach the UnhandledException handler.

private void Throw( Exception exception )
{
    uiContext.Post( arg => throw exception, null );
    throw new OperationCanceledException();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM