MicrosoftEdge / MicrosoftEdge/WebView2Feedback

WebView2 Disposal method throws an unhandled InvalidCastException when called from the HwndHost Finalizer

Open
#2,420 2 comments 0 reactions 1 assignee View on GitHub

@bradp0721 is already working on this.

Since May 4, 2022.

bug tracked
Dominant language
PowerShell
Stars
526
Forks
67
PR merge metrics
No merged PRs in 30d

Description

When the GC Finalizer Thread is cleaning up objects, it will invoke the Finalizer of HwndHost, which WebView2 inherits. This calls WebView2.Dispose(false).

The problem is, the WebView2 Dispose method must be called from the UI thread, otherwise we encounter an InvalidCastException, due to an object being accessed from a thread that does not own it. The UI thread is the thread that should be disposing of this object.

Now, in proper usage, we can simply call the Dispose method ourselves from the correct thread, but this is not always desired. In cases where the application is exiting forcefully (e.g. via Application.Current.Shutdown()), we don't care about calling the dispose method, or calling the dispose methods is not practical/achievable .

I think the solution would be to attempt to finalize the object on the UI thread (within the WebView2 Dispose method) - or by defining a Finalizer on the WebView2 object that attempts to dispose on the UI thread. Should be achievable using the Dispatcher. I have tried to do this myself, but it seems the GC Finalizer Thread has a hard time actually executing code using the Dispatcher, the program just exits before the Dispatcher is invoked.

Why is this a problem?

  • Because, we don't want Event Viewer to have unnecessary events log anytime the application exists forcefully.
  • Because the current implementation of the finalizer literally does not do it's job properly when called on WebView2 objects, instead it throws an exception 100% of the time. The finalizer should run cleanly, regardless of whether the dispose method has been explicitly called or not.

What's the work around?
Well, if you cannot call Dispose yourself (because you're trying to exit the application), then you'll have to suppress the finalizer at some point after the WebView2 object has been created (can be done while you're also calling the various initialization functions). As you may be able to tell, this isn't an ideal situation. We shouldn't have to suppress a broken finalizer.

The only advantage I can see is if the programmer has forgotten to call Dispose and the finalizer is called instead, leading to this unhandled exception.

Thoughts?

AB#39614813

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.