Summary
WebView2BreadcrumbHost's constructor performs an unhook-then-hook sequence intended to be
idempotent across pooled-viewer reuse, but the unhook cannot remove the previous instance's
subscription. When a new WebView2BreadcrumbHost is constructed over a WebView2 control that a
prior host instance already wrapped, the prior instance stays subscribed to the control's
CoreWebView2InitializationCompleted event. The old host is kept alive by the control, and
initialization completion is handled more than once.
Environment
- OS/version: Windows 11 Pro 10.0.26200
- Runtime: .NET Framework 4.8.1 WinForms VSTO add-in with Microsoft WebView2
- Affected path: pooled viewer reuse (
EfcViewerQueue / ItemViewerQueue recycling a viewer whose
Designer-owned WebView2 control is retained across uses)
Steps to Reproduce
- Construct a
WebView2BreadcrumbHost over a Designer-owned WebView2 control.
- Recycle the pooled viewer so a second
WebView2BreadcrumbHost is constructed over the same
control instance.
- Drive CoreWebView2 initialization to completion.
- Observe that both host instances handle the completion:
IsCoreInitialized is set and
CoreInitialized is raised on the stale instance as well as the live one.
Expected Behavior
Exactly one host instance - the current one - is subscribed to the control's events, and exactly
one CoreInitialized notification reaches the controller per initialization.
Actual Behavior
Both instances remain subscribed. The stale instance is retained for the lifetime of the control.
Logs / Screenshots
(not provided in potential file)
Impact / Severity
Consequences are a managed-object retention leak (each recycled viewer accumulates one dead host
plus its event-handler chain) and duplicated CoreInitialized / MessageReceived notifications
routed to BreadcrumbBridgeRouter.NotifyCoreInitialized. Duplicate notification can produce
duplicate breadcrumb document initialization work. Severity is Medium rather than High because the
stale host's handler does not throw and the observable breadcrumb output is idempotent in the
common path.
Source
From: docs/features/potential/2026-08-07-webview2breadcrumbhost-handler-retention-pooled-viewer.md
Summary
WebView2BreadcrumbHost's constructor performs an unhook-then-hook sequence intended to beidempotent across pooled-viewer reuse, but the unhook cannot remove the previous instance's
subscription. When a new
WebView2BreadcrumbHostis constructed over aWebView2control that aprior host instance already wrapped, the prior instance stays subscribed to the control's
CoreWebView2InitializationCompletedevent. The old host is kept alive by the control, andinitialization completion is handled more than once.
Environment
EfcViewerQueue/ItemViewerQueuerecycling a viewer whoseDesigner-owned
WebView2control is retained across uses)Steps to Reproduce
WebView2BreadcrumbHostover a Designer-ownedWebView2control.WebView2BreadcrumbHostis constructed over the samecontrol instance.
IsCoreInitializedis set andCoreInitializedis raised on the stale instance as well as the live one.Expected Behavior
Exactly one host instance - the current one - is subscribed to the control's events, and exactly
one
CoreInitializednotification reaches the controller per initialization.Actual Behavior
Both instances remain subscribed. The stale instance is retained for the lifetime of the control.
Logs / Screenshots
(not provided in potential file)
Impact / Severity
Consequences are a managed-object retention leak (each recycled viewer accumulates one dead host
plus its event-handler chain) and duplicated
CoreInitialized/MessageReceivednotificationsrouted to
BreadcrumbBridgeRouter.NotifyCoreInitialized. Duplicate notification can produceduplicate breadcrumb document initialization work. Severity is Medium rather than High because the
stale host's handler does not throw and the observable breadcrumb output is idempotent in the
common path.
Source
From: docs/features/potential/2026-08-07-webview2breadcrumbhost-handler-retention-pooled-viewer.md