ShutDownListener中的TaskCanceledException

时间:2018-06-18 09:53:16

标签: c# .net

我们目前看到很多class Employee{ let id:Int let name:String let salary:Int init?(){ guard let name = readLine() else { return nil } self.name = name guard let idString = readLine(), let id = Int(idString) else { return nil } self.id = id guard let salaryString = readLine(), let salary = Int(salaryString) else { return nil} self.salary = salary } } var flag="y" var empData:[Employee]=[] repeat { if let employee = Employee() { empData.append(employee) } else { // Display error message to the user } flag=readLine() ?? "" } while(flag=="y") 被抛弃TaskCanceledException。这开始于5月中旬,可能与.Net或Windows 10的一些更新有关。我们在旧版本(〜2岁)和我们软件的新版本中看到了它,它刚刚开始在所有版本中启动。我们将旧版本的.Net 4客户端配置文件和带有较新版本的.Net 4.5.1。

完整堆栈跟踪是:

  

TaskCanceledException at   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务   任务)   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务   任务)   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务   任务)在System.Windows.Threading.DispatcherOperation.Wait(TimeSpan   超时)at   System.Windows.Threading.Dispatcher.InvokeImpl(的DispatcherOperation   operation,CancellationToken cancellationToken,TimeSpan timeout)at   System.Windows.Threading.Dispatcher.Invoke(动作回调,   DispatcherPriority优先级,CancellationToken cancellationToken,   TimeSpan超时)在MS.Internal.WeakEventTable.OnShutDown()处   MS.Internal.ShutDownListener.HandleShutDown(Object sender,EventArgs   E)

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

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

2 个答案:

答案 0 :(得分:4)

我也一直在看这个。如果查看源〜278,关机期间有300ms的任意时间限制: 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的所有使用。

答案 1 :(得分:0)

似乎有一种解决方法,至少对于.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终结器线程上创建xref:System.Windows.Threading.Dispatcher?displayProperty = nameWithType。通过使弱事件的清理具有线程意识,此问题已在.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>