TaskCanceledException in ShutDownListener

There seems to be a workaround, at least for .NET Framework 4.7.2

https://github.com/Microsoft/dotnet/blob/master/Documentation/compatibility/wpf-AppDomain-shutdown-handling-may-now-call-Dispatcher.Invoke-in-cleanup-of-WeakEvents.md

Change Description

In .NET Framework 4.7.1 and earlier versions, WPF potentially creates a System.Windows.Threading.Dispatcher on the .NET finalizer thread during AppDomain shutdown. This was fixed in .NET Framework 4.7.2 and later versions by making the cleanup of weak events thread-aware. Due to this, WPF may call System.Windows.Threading.Dispatcher.Invoke to complete the cleanup process.

In certain applications, this change in finalizer timing can potentially cause exceptions during AppDomain or process shutdown. This is generally seen in applications that do not correctly shut down dispatchers running on worker threads prior to process or AppDomain shutdown. Such applications should take care to properly manage the lifetime of dispatchers.

Recommended Action

In .NET Framework 4.7.2 and later versions, developers can disable this fix in order to help alleviate (but not eliminate) timing issues that may occur due to the cleanup change.

To disable the change in cleanup, use the following AppContext flag.

<configuration>
    <runtime>
        <AppContextSwitchOverrides value="Switch.MS.Internal.DoNotInvokeInWeakEventTableShutdownListener=true"/>
    </runtime>
</configuration>

I've been seeing this too. There's an arbitrary 300ms time limit during shutdown if you look at the source ~278: https://referencesource.microsoft.com/#WindowsBase/Base/MS/Internal/WeakEventTable.cs

try
{
    Dispatcher.Invoke((Action)OnShutDown, DispatcherPriority.Send, CancellationToken.None, TimeSpan.FromMilliseconds(300));
    succeeded = true;
}
catch (TimeoutException)
{
}

It raises even though the internal collections in the WeakEventTable are all emptied out.

enter image description here

Whoever wrote it didn't anticipate the runtime throwing TaskCanceledException since probably it never used to. The workaround I'm taking is to remove all use of WeakEventManager.

Tags:

C#

.Net