【问题标题】:TaskCanceledException in ShutDownListenerShutDownListener 中的 TaskCanceledException
【发布时间】:2018-06-18 09:53:15
【问题描述】:

我们目前看到很多TaskCanceledExceptionMS.Internal.ShutDownListener.HandleShutDown 抛弃。这从 5 月中旬开始,可能与 .Net 或 Windows 10 的某些更新有关。我们在旧版(约 2 年)和新版软件中都看到了这一点,而且它刚刚在所有版本中开始。我们针对较旧版本的 .Net 4 客户端配置文件和较新版本的 .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(时间跨度 超时)在 System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherOperation 操作,CancellationToken 取消令牌,TimeSpan 超时)在 System.Windows.Threading.Dispatcher.Invoke(动作回调, DispatcherPriority 优先级,CancellationToken cancelToken, TimeSpan 超时)在 MS.Internal.WeakEventTable.OnShutDown() 在 MS.Internal.ShutDownListener.HandleShutDown(对象发送者,EventArgs e)

问题是:这是什么原因造成的?

目前,我们正在寻找找到根本原因并最终解决此问题的方法。当然,最后我们可以简单地抓住它,但这不是一个实际的解决方案。欢迎任何方向的提示。我们想更新这个问题,因为我们获得了更多的洞察力,以便能够为以后遇到这个问题的人提供信息。

【问题讨论】:

    标签: c# .net


    【解决方案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 中的内部集合都被清空了,它也会引发。

    编写它的人没有预料到运行时会抛出TaskCanceledException,因为它可能从来没有使用过。我正在采取的解决方法是删除所有对 WeakEventManager 的使用。

    【讨论】:

    • 啊,谢谢你指点方向!不幸的是,我们使用了依赖于 WeakEventManager 的 Prism,但我可以在这个方向上进一步研究我们可以在这里做什么。目前的主要问题是,我们无法在我们的机器上真正重现它,我们只能从用户那里听到。
    • 目前,我们使用此洞察力在堆栈跟踪中使用 Wea​​kEventManager 过滤掉此异常,并将尝试与 Microsoft 联系以最终解决根本原因。感谢您为我们指明正确的方向!
    • 您是否有机会就此与 mocrosoft 联系?如果对此事件有任何参考,请分享。
    • 如果(希望)现在找到了在此处提交此问题的正确位置:developercommunity.visualstudio.com/content/problem/284294/… 我也会密切关注这一点,并会尝试在此处更新更多有用的信息。
    • 有一个指向这个文档的链接:在 VS 社区中,发布了一个指向这个文档的链接,这可能有点解释:github.com/Microsoft/dotnet/blob/master/Documentation/… 它谈到应用程序没有正确处理 Dispatcher 生命周期,但我找不到任何关于如何处理它的文档,以及这是否随着.Net 4.7.2而改变。
    【解决方案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 可能会在 AppDomain 关闭期间在 .NET 终结器线程上创建 System.Windows.Threading.Dispatcher。这在 .NET Framework 4.7.2 及更高版本中已通过清除弱事件线程感知得到修复。因此,WPF 可能会调用System.Windows.Threading.Dispatcher.Invoke 来完成清理过程。

    在某些应用程序中,终结器时间的这种变化可能会在AppDomain 或进程关闭期间导致异常。这通常出现在未正确关闭在进程或AppDomain 关闭之前在工作线程上运行的调度程序的应用程序中。此类应用程序应注意正确管理调度程序的生命周期。

    推荐操作

    在 .NET Framework 4.7.2 及更高版本中,开发人员可以禁用此修复,以帮助缓解(但不能消除)由于清理更改而可能出现的计时问题。

    要禁用清理更改,请使用以下AppContext 标志。

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

    【讨论】:

      猜你喜欢
      • 2019-10-21
      • 2020-12-12
      • 1970-01-01
      • 2012-10-13
      • 2015-09-20
      • 2019-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多