We are currently seeing a lot of TaskCanceledException
thrown off MS.Internal.ShutDownListener.HandleShutDown
. This started in the middle of may and could be related to some Update to .Net or Windows 10. We see this in old (~2 years old) and new versions of our software and it just started across all versions. We target .Net 4 Client profile with older version and .Net 4.5.1 with newer versions.
The full stack trace is:
TaskCanceledException at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Windows.Threading.DispatcherOperation.Wait(TimeSpan timeout) at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherOperation operation, CancellationToken cancellationToken, TimeSpan timeout) at System.Windows.Threading.Dispatcher.Invoke(Action callback, DispatcherPriority priority, CancellationToken cancellationToken, TimeSpan timeout) at MS.Internal.WeakEventTable.OnShutDown() at MS.Internal.ShutDownListener.HandleShutDown(Object sender, EventArgs e)
The question is: what is causing this?
Right now, we are looking for approaches to find the root cause and eventually a fix for this. Of course, we can simply catch it in the end, but that's not an actual solution. Any hints in the direction are welcome. We'd like to update this question as we gain more insight to be able to provide information for people coming across this later.
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
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With