TaskCanceledException в ShutDownListener

В настоящее время мы видим много TaskCanceledException сбрасываемое с MS.Internal.ShutDownListener.HandleShutDown. Это началось в середине мая и могло быть связано с некоторым обновлением до.Net или Windows 10. Мы видим это в старых (~ 2 года) и новых версиях нашего программного обеспечения, и это просто началось во всех версиях. Мы настраиваем профиль.Net 4 Client с более старой версией и.Net 4.5.1 с более новыми версиями.

Полная трассировка стека:

TaskCanceledException в System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (задача задачи) в System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (задача задачи) в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (задача задачи) в System.Windows.Threading. DispatcherOperation.Wait(TimeSpan timeout) в System.Windows.Threading.Dispatcher.InvokeImpl (операция DispatcherOperation, CancellationToken cancelationToken, тайм-аут TimeSpan) в System.Windows.Threading.Dispatcher.Invoke(Action callback, приоритет DispatcherPriority, CancellationToken cancelationToken, тайм-аут TimeSpan) в MS.Internal.WeakEventTable.OnShutDown() в MS.Internal.ShutDownListener.HandleShutDown (отправитель объекта, EventArgs e)

Вопрос в том, что вызывает это?

Сейчас мы ищем подходы, чтобы найти основную причину и в конечном итоге исправить это. Конечно, мы можем просто поймать его в конце, но это не настоящее решение. Любые намеки в направлении приветствуются. Мы хотели бы обновить этот вопрос, поскольку мы получили больше информации, чтобы иметь возможность предоставлять информацию людям, которые сталкиваются с этим позже.

Ответ 1

Я тоже это видел. Там, где вы смотрите на источник ~ 278, существует произвольный 300-минутный временной интервал: 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)
{
}

Он поднимается, хотя внутренние коллекции в WeakEventTable все освобождены.

enter image description here

Тот, кто его написал, не ожидал, что среда выполнения будет TaskCanceledException поскольку, вероятно, она никогда не использовалась. Обходной путь, который я принимаю, - удалить все использование WeakEventManager.

Ответ 2

Кажется, есть обходной путь, по крайней мере, для.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

изменить описание

В.NET Framework 4.7.1 и более ранних версиях WPF потенциально создает xref: System.Windows.Threading.Dispatcher? DisplayProperty = nameWithType в потоке финализатора.NET во время завершения работы AppDomain. Это было исправлено в.NET Framework 4.7.2 и более поздних версиях путем очистки слабых событий с учетом потоков. Из-за этого WPF может вызвать xref: System.Windows.Threading.Dispatcher.Invoke% 2A? DisplayProperty = nameWithType для завершения процесса очистки.

В некоторых приложениях это изменение времени финализатора может вызвать исключения во время AppDomain или завершения процесса. Как правило, это наблюдается в приложениях, которые некорректно завершают работу диспетчера, работающего в рабочих потоках, до завершения процесса или AppDomain. Такие приложения должны позаботиться о правильном управлении временем жизни диспетчеров.

Рекомендуемое действие

В.NET Framework 4.7.2 и более поздних версиях разработчики могут отключить это исправление, чтобы облегчить (но не устранить) проблемы синхронизации, которые могут возникнуть из-за изменения очистки.

Чтобы отключить изменение в очистке, используйте следующий флаг AppContext.

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