dotnet/wpf · error · TimeoutException

The operation has timed out.

Error message

The operation has timed out.

What it means

Dispatcher.InvokeImpl waits for the invoked operation to complete under a CancellationToken tied to the timeout. If the wait ends because the cancellation token fired due to the timeout — and not because of an external cancellation — the dispatcher throws TimeoutException with the default message 'The operation has timed out.' This distinguishes a genuine timeout from a user-requested cancellation, which is rethrown as-is.

Solutions

  1. Increase the timeout, or pass TimeSpan.FromMilliseconds(-1) to wait indefinitely when acceptable.
  2. Avoid cross-thread Invoke when the target thread might wait on the caller (deadlock); use BeginInvoke/InvokeAsync (fire-and-forget) or marshal results with await.
  3. Catch TimeoutException at the call site and decide on retry/abort behavior.
  4. Ensure the UI thread's dispatcher queue is not starved (avoid 100+ ms synchronous work on it).

Example fix

// before
dispatcher.Invoke(() => Compute(), DispatcherPriority.Normal, TimeSpan.FromSeconds(1));
// after
var op = dispatcher.BeginInvoke(() => Compute());
// do not block the worker on the UI thread; continue asynchronously
op.Completed += (s, e) => { /* use op.Result */ };
Defensive patterns

Strategy: try-catch

Validate before calling

if (Dispatcher.FromThread(targetThread) == null || targetThread.IsAlive == false)
    return; // do not block on a dead/absent dispatcher
dispatcher.Invoke(work, DispatcherPriority.Send, TimeSpan.FromSeconds(30));

Try / catch

try
{
    dispatcher.Invoke(work, DispatcherPriority.Normal, TimeSpan.FromSeconds(30));
}
catch (TimeoutException)
{
    // UI thread busy or deadlocked; retry with a longer timeout or go async
    dispatcher.BeginInvoke(work);
}

Prevention

When it happens

Trigger: Calling Dispatcher.Invoke (synchronous, cross-thread) where the dispatched operation cannot run within the specified timeout because the target dispatcher thread is busy/blocked with higher-priority or long-running work, or is itself deadlocked.

Common situations: Invoke from a worker thread onto a UI thread that is blocked waiting on the worker (classic deadlock until timeout); rendering/layout storms keeping the UI thread busy past the timeout; timeouts set too short (e.g. seconds) for heavy work.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/8c9a90b505e8d470. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/Threading/Dispatcher.cs:1381

                    // This should not block because either the operation
                    // is using the old async sematics, or the operation
                    // completed successfully.
                    result = operation.Result;
                }
                catch(OperationCanceledException)
                {
                    Debug.Assert(operation.Status == DispatcherOperationStatus.Aborted);

                    // New async semantics will throw an exception if the
                    // operation was aborted.  Here we convert that
                    // exception into a timeout exception if the timeout
                    // has expired (admittedly a weak relationship
                    // assuming causality).
                    if (ctTimeout.IsCancellationRequested)
                    {
                        // The operation was canceled because of the
                        // timeout, throw a TimeoutException instead.
                        throw new TimeoutException();
                    }
                    else
                    {
                        // The operation was canceled from some other reason.
                        throw;
                    }
                }
                finally
                {
                    ctTimeoutRegistration.Dispose();
                    ctsTimeout?.Dispose();
                }
            }

            return result;
        }

        /// <summary>

View on GitHub (pinned to 81131a70a4)