无限循环导致时间管理器失效

14
我在跟踪一个非常棘手的WPF应用程序缺陷。 错误信息是:

在布局/呈现过程中,似乎由于重复使TimeManager无效而导致无限循环。

堆栈跟踪(仅供参考)为:

在System.Windows.Media.MediaContext.RenderMessageHandlerCore(Object resizedCompositionTarget) at System.Windows.Media.MediaContext.RenderMessageHandler(Object resizedCompositionTarget) at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs) at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)

这是一个间歇性的缺陷,我唯一能够捕获到它的地方是在应用配置文件中,我正在捕获Application_DispatcherUnhandledException消息。 我的应用程序中的所有内容都包装在try catch块中,但是这最终却在捕获未处理的异常的位置上。
有人对此有任何见解吗?我在互联网上搜索了一些东西,但没有找到任何有用的信息,想知道这里是否有人能提供一些见解或者如何追踪此问题的想法。目前,我会吞下这个异常并让应用程序继续运行,因为它似乎没有任何影响(除了崩溃)。

它在所有机器上(在所有环境中)都失败了吗?您是否拥有包括所有热修补程序的最新版本的WPF? - Halvard
在所有环境中,所有机器都失败了,是的,我们已经更新了所有服务包。然而,我们正在使用.NET 4.0版本而不是4.5版本,因此我们没有最新版本的WPF。我们不太可能很快升级到4.5。 - Mike Malter
3个回答

4
预计您无法在代码中捕获异常:您的错误来自应用程序的Xaml部分,最可能是动画。
因此,无论您是在Xaml中创建动画还是使用代码,例如,当动画B停止时触发动画A开始,同时让动画B停止。所以你有一个无限循环:A开始->B停止->A开始->B停止->...
实际上有许多无限循环的情况。它们可能由CurrentStateInvalidated处理程序或Completed处理程序或CurrentTimeInvalidated触发,并且我可能会忘记一些使用其他类型的触发器(鼠标等)和/或三个先前提到的触发器的情况。可能代码太复杂了。
删除所有动画以测试此场景。
尝试清晰地重现错误并检查哪些处理程序可能涉及这样一个循环并不断相互调用。
...您也可以在处理程序中使用计数器,并且例如,复选框会警告您已达到给定(大)数量的调用次数。此复选框还将给出处理程序的名称。单击几次“确定”以检查循环成员。
您可以在发布版本中保留类似的代码,并在达到该数字时仅写入一次日志文件,然后处理程序将始终在执行任何操作之前返回。比崩溃更好。
...或者只需进行代码审查即可显示可能的循环。
希望这能有所帮助。
编辑: 请听取我的建议:
A)删除所有动画,测试应用程序,看看会发生什么。 B)如果您不再看到错误:这是原因。
C)然后,在anims中尝试删除最“危险”的触发器——事件触发器。 您可以使用将XAML放入注释中,因此只需复制粘贴触发器即可在动画之后。
D)再次测试:如果您不再看到错误,则为事件触发器 E)审查所有事件触发器并查看是否存在我上面描述的循环。
如果在D)中仍然看到错误,请使用其他触发器(属性触发器/数据触发器)重复C)。
第二个想法:它可能是一个属性/数据触发器,其中某些数据经常更改...
发布一些xaml。
我有一个想法:尝试在Application_DispatcherUnhandledException中设置断点,然后观察内部异常的内部异常...直到达到MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen异常,然后您就可以知道源。我不会感到惊讶如果是Infragistics网格导致了这个问题。我曾经测试过Telerik的控件,在与一些可怕的问题作斗争之后,我只是回归了自己定制的经典网格:既节省了时间又节省了金钱。我很快地观察了这个网格:它们像你用这个网格的转换器自定义样式一样存在问题。--> 如果可能的话,请尝试使用标准DataGrid。
--> 如果没有错误,我们找到了根本原因:尝试使用“裸露”的Infragistic网格,然后测试,然后添加样式,再测试。我不确定您是否可以不使用转换器进行测试。尽管如此,始终可以使视图模型公开“转换”属性...

再说一遍:在您的帖子中,引用一些xaml,描述故障案例。

Vincent,感谢您抽出时间回答我的问题。您以前有遇到过异常吗?我的情况是,我正在与一位知道如何在xaml中编码但不具备技术倾向的平面设计师合作。 - Mike Malter
我刚刚又遇到了这个异常,没有涉及任何动画。我正在关闭一个包含Infragistics网格、文本框和四个按钮的对话框时抛出了异常。异常是在我关闭对话框时抛出的。 - Mike Malter
Vincent,我问你是否直接遇到过这个问题,并不是想暗示你在误导我。我非常感谢你的热心帮助。我只是想知道你以前是否遇到过这种情况。我的平面设计师度假回来后,我将让她从动画角度来看这个问题。虽然网格并没有直接使用动画,但这并不意味着设计师没有在xaml代码的深处使用它。 - Mike Malter
我在使用进度条时遇到了异常,但是通过在相关的XAML中注释掉动画(白色光晕)来防止它。不过我仍然在想为什么会出现这种情况 :P - EricG
应该标为答案。谢谢,GameAlchemist。 - Maryna Klokova
显示剩余3条评论

-2

Rodrigo,您的链接是针对WinForms的,而我的问题与WPF有关。我查看了您发布的链接,但它并不相关。 - Mike Malter
我理解这一点,这就是为什么我认为你应该看一下。在WPF中没有TimerManager类的引用。有可能您使用了错误的引用或者某些WinForms类导致了WPF崩溃吗? - rodrigogq

-2
有时候异常非常棘手。其中一个建议是在没有异常对象的情况下使用catch块。因此,您可以从以下方式更新catch块:
 catch(Exception ex)
{
..
}

    catch()
{
..
}

还有其他低级别的异常很难捕获,正如Peli在回复中提到的那样。


Avani,感谢您抽出时间回答我的问题。我很想知道您认为使用空catch如何帮助我追踪问题? - Mike Malter
嗨MikeMalter,抱歉回复晚了。空catch可能会帮助您缩小到引发异常的代码区域。 - avani gadhai
一个空的 catch 怎么做到这一点?谢谢。 - Mike Malter
1
我理解你的意思,catch(Exception)只捕获类型为System.Exception的异常。由于我将所有内容都包裹在try/catch(Exception)块中,且TimeManager异常从未被升级为System.Exception,如果我不带参数捕获异常,可能会捕获TimeManager异常。问题是该异常是间歇性的,并且会在随机位置和随机条件下发生,此时重新编写应用程序以捕获异常并非选项。但是,你的答案到目前为止是最好的,所以你得到了奖励。 - Mike Malter
1
在.NET领域中,没有不继承自System.Exception的异常。这个答案完全是错误的。https://referencesource.microsoft.com/#PresentationCore/Core/CSharp/System/Windows/Media/MediaContext.cs,1874 - Brannon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接