.NET 4.0 WPF自动化异常

8
我有一个在.NET 3.5 SP1中运作良好的项目。现在升级到.NET 4.0后,我遇到了自动化异常问题。
我已经搜索了整个项目,没有任何与自动化有关的内容。同时,谷歌搜索也无法确认这是否是一个错误。该错误只会在少数电脑上随机发生。因此,我认为完全禁用自动化可能是.NET 4.0的一个bug?
Exception Source: PresentationCore
Message: Object reference not set to an instance of an object.
Stack Trace:
   at System.Windows.Automation.Peers.AutomationPeer.EnsureChildren()
   at System.Windows.Automation.Peers.AutomationPeer.UpdateChildrenInternal(Int32 invalidateLimit)
   at System.Windows.Automation.Peers.AutomationPeer.UpdateSubtree()
   at System.Windows.Automation.Peers.AutomationPeer.UpdateSubtree()
   at System.Windows.Automation.Peers.AutomationPeer.UpdatePeer(Object arg)
   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)
   at System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.DispatcherOperation.InvokeImpl()
   at System.Threading.ExecutionContext.runTryCode(Object userData)
   at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Windows.Threading.DispatcherOperation.Invoke()
   at System.Windows.Threading.Dispatcher.ProcessQueue()
   at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   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)
   at System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   at System.Windows.Application.RunInternal(Window window)
   at System.Windows.Application.Run()

不知道答案,但建议您继续观察。如果问题确实是随机的,那么可能是 .net 4.0 的一个 bug。否则就不是。 - Peter Long
我们遇到了同样的问题,当我移除一些样式时问题就消失了。当我们找出具体是哪个部分引起的时候,我会在这里写下来。 - sinelaw
好的,在我们的情况下,这与日期时间选择器日历样式的故事板动画有关。我们仍然没有调查出确切的原因,但我们将删除动画以解决它。 - sinelaw
2
更新:事实证明,动画可能并不是确切的原因。有人在按钮上放置了一个全局样式。结果,DateTimePicker 样式被搞砸了。他们“修复”的方法是用一堆 XAML 代码覆盖 DateTimePicker 样式,可能是从某个网站复制过来的。这个样式非常复杂。当我删除了复杂的自定义 DateTimePicker 样式时,异常就消失了。我还删除了全局 Button 样式覆盖,这使得 DateTimePicker 再次正常显示。因此,仅仅通过删除大量的 XAML 样式代码,我就避免了异常。 - sinelaw
顺便说一下,这仍然是一个 WPF 的 bug,只是记录一下。我只是在说我如何避免它的。 - sinelaw
我在使用日期时间选择器时遇到了相同的问题,如果我找到了任何解决方法,我会在这里发布。 - Ivan
3个回答

5
EnsureChildren方法相当简单:
private void EnsureChildren()
{
    if (!this._childrenValid || this._ancestorsInvalid)
    {
        this._children = this.GetChildrenCore();
        if (this._children != null)
        {
            int count = this._children.Count;
            for (int i = 0; i < count; i++)
            {
                this._children[i]._parent = this;
                this._children[i]._index = i;
                this._children[i]._hwnd = this._hwnd;
            }
        }
        this._childrenValid = true;
    }
}

唯一可能出现NullReferenceException的代码是this.children[i]。通常,自定义WPF控件的自动化对等体会实现GetChildrenCore方法。因此,很有可能其中一个返回null。如果您有任何自定义控件或第三方控件实现了自定义自动化对等体,则这将是一个可能的原因。
您可以通过创建自定义类并重写OnCreateAutomationPeer方法并返回null来逐个元素地禁用UI自动化。这是我所知道的唯一禁用自动化的方法。
您最好的选择可能是删除UI的各个元素以缩小引起问题的控件范围。

谢谢!我有所有自定义控件的源代码,但似乎没有实现自定义自动化对等体。我将尝试覆盖项目中所有窗口的OnCreateAutomationPeer方法。 - Luke
@Luke:你能解决这个问题吗?如果可以的话,你能提供一些你所做的事情的信息作为答案吗?我们目前也遇到了同样的问题。 - O. R. Mapper

1

0

这是WPF的一个bug。如果没有为日期标题行(在日历中显示天名称的部分)定义数据模板,则CalendarAutomationPeer.GetChildrenCore会返回nulls。这会导致空指针异常,通常会在WPF的某个地方处理,但有时会导致应用程序崩溃。

为了解决这个问题,只需定义DayTitleTemplate(如Friggers在评论中提到以及这篇文章中How can I change the DataTemplate for DayTitleTemplate in a CalendarItemTemplate)。


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