dotnet/wpf · error · ArgumentException
SR.HwndTarget_InvalidWindowThread
Error message
SR.HwndTarget_InvalidWindowThread
What it means
The target window must also belong to the calling thread: AttachToHwnd compares the hwnd's thread id with GetCurrentThreadId() and throws ArgumentException (SR.HwndTarget_InvalidWindowThread) on mismatch. WPF rendering targets are thread-affine, so the window must live on the thread creating the HwndTarget.
Solutions
- Create the HwndSource on the same thread that created the HWND
- Marshal construction to the window's owning thread via Dispatcher.BeginInvoke
- If using a dedicated UI thread, create the window handle on that same thread
Example fix
// before Task.Run(() => new HwndSource(0, 0, 0, 0, 0, "x", uiThreadHwnd)); // throws // after dispatcherOfOwningThread.Invoke(() => new HwndSource(0, 0, 0, 0, 0, "x", hwnd));
Defensive patterns
Strategy: validation
Validate before calling
GetWindowThreadProcessId(hwnd, out _); if (threadId != SafeNativeMethods.GetCurrentThreadId()) Marshal to owning thread before creating the source;
Type guard
bool IsOnCurrentThread(IntPtr hwnd) => GetWindowThreadId(hwnd) == SafeNativeMethods.GetCurrentThreadId();
Try / catch
try { new HwndSource(...); } catch (ArgumentException) { /* dispatch to owning thread's Dispatcher */ } Prevention
- Create HwndSource on the same thread that owns the HWND
- Keep all WPF interop setup on a single Dispatcher thread
- Avoid Task.Run around window/handle creation
When it happens
Trigger: Constructing an HwndSource/HwndTarget on thread B for an HWND created on thread A (e.g. building UI on a background/worker thread using a handle created by the UI thread).
Common situations: Multi-threaded apps creating windows on the main thread but initializing WPF interop content on a worker; COM/threading mismatches in mixed Win32/WPF apps.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- SR.Format(SR.AXNohWnd, GetType().Name)
- SR.HwndTarget_InvalidWindowHandle
- SR.HwndTarget_InvalidWindowProcess
- SR.HwndTarget_WindowAlreadyHasContent
- 0x80070057
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/b325bd7bd343bff0.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/InterOp/HwndTarget.cs:538
);
if (!UnsafeNativeMethods.IsWindow(new HandleRef(this, hwnd)))
{
throw new ArgumentException(
SR.HwndTarget_InvalidWindowHandle,
nameof(hwnd)
);
}
else if (processId != Environment.ProcessId)
{
throw new ArgumentException(
SR.HwndTarget_InvalidWindowProcess,
nameof(hwnd)
);
}
else if (threadId != SafeNativeMethods.GetCurrentThreadId())
{
throw new ArgumentException(
SR.HwndTarget_InvalidWindowThread,
nameof(hwnd)
);
}
int hr = VisualTarget_AttachToHwnd(hwnd);
if (HRESULT.Failed(hr))
{
if (hr == unchecked((int)0x80070005)) // E_ACCESSDENIED
{
throw new InvalidOperationException(
SR.HwndTarget_WindowAlreadyHasContent
);
}
else
{
HRESULT.Check(hr);View on GitHub (pinned to 81131a70a4)