MicrosoftEdge / MicrosoftEdge/WebView2Feedback
[Problem/Bug]: WPF: GraphicsItemD3DImage.Dispose(bool) disposes managed _device outside the if (disposing) block
Nobody has claimed this yet.
- Dominant language
- PowerShell
- Stars
- 526
- Forks
- 67
- PR merge metrics
- No merged PRs in 30d
Description
What happened?
In Microsoft.Web.WebView2.Wpf (used by WebView2CompositionControl), the internal class Microsoft.Web.WebView2.Wpf.GraphicsItemD3DImage implements the standard Dispose(bool disposing) pattern, but the call to _device?.Dispose() is placed outside the if (disposing) block.
Decompiling Microsoft.Web.WebView2.Wpf.dll shows (simplified):
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
// other managed cleanup...
}
_device?.Dispose(); // <-- BUG: managed object disposed unconditionally
_disposed = true;
}
_device is a managed IDisposable object. Per the standard .NET dispose pattern, managed objects must only be disposed when disposing == true (i.e. when called from Dispose()), never on the finalizer path (Dispose(false)).
Why this is a problem:
When GraphicsItemD3DImage is collected without an explicit Dispose() call and its finalizer runs:
Dispose(false)still calls_device?.Dispose()on the finalizer thread.- At that point
_devicemay already have been finalized itself (finalization order between reachable-from-finalizable objects is undefined), so this can touch an already-reclaimed object. - It also invokes D3D device teardown from the finalizer thread rather than the thread that owns the device, which is unsafe for D3D11 objects and can cause intermittent
ObjectDisposedException, access violations, or device-context corruption that are very hard to diagnose in host applications.
Expected behavior:
_device?.Dispose() should be moved inside the if (disposing) block, so it is only executed on the explicit dispose path:
if (disposing)
{
// other managed cleanup...
_device?.Dispose();
}
Importance
Important. My app's user experience is significantly compromised.
Runtime Channel
Stable release (WebView2 Runtime)
Runtime Version
No response
SDK Version
1.0.4078.44
Framework
WPF
Operating System
Windows 11
OS Version
No response
Repro steps
This is a code-level defect, observable by inspection:
- Reference
Microsoft.Web.WebView21.0.4078.44. - Decompile
Microsoft.Web.WebView2.Wpf.dll(e.g. with ILSpy). - Inspect
Microsoft.Web.WebView2.Wpf.GraphicsItemD3DImage.Dispose(bool). - Observe
_device?.Dispose()outside theif (disposing)block, so it also runs on the finalizer path.
https://github.com/Hannott/WebView2CompositionControl
Repros in Edge Browser
No, issue does not reproduce in the corresponding Edge version
Regression
No, this never worked
Last working version (if regression)
No response
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by inspecting Microsoft.Web.WebView2.Wpf.GraphicsItemD3DImage.Dispose(bool) in Microsoft.Web.WebView2.Wpf.dll, using the decompilation described in the issue. Confirm that _device?.Dispose() is only reached on the explicit dispose path, then verify the resulting behavior against the standard Dispose pattern; no specific test file is named.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- desktop
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 48/100