【问题标题】:NullReferenceException from PresentationFramework.dll来自 PresentationFramework.dll 的 NullReferenceException
【发布时间】:2013-04-21 04:14:01
【问题描述】:

我正在处理一个奇怪的 NullReferenceException,它显然是由 ItemAutomationPeer 类的 GetNameCore() 函数触发的。

该异常的详细信息如下,但真正有趣的是它不会发生在我运行 Windows 7 的开发机器或我们测试过的其他 Windows 7 计算机上。它只发生在我的 Windows 8 Pro 测试机器上。

尝试编辑 WPF DataGrid 控件中的单元格时显然会引发异常。

我整天都在尝试追踪它,但没有成功。我尝试使用 Visual Studio 远程调试该过程并单步执行代码,但似乎没有任何用户代码触发异常。它显然是由 PresentationFramework.Dll 内的一系列事件执行的,异常只是通过 AppDomain 冒泡并最终导致应用程序崩溃。

如果有人能想到任何可能导致此问题的原因,或解决此问题的方法,那将真的很有帮助。

Exception Type:         System.NullReferenceException
Exception Message:  Object reference not set to an instance of an object.
Method Information: System.String GetNameCore()
Exception Source:   PresentationFramework

Stack Trace
  at System.Windows.Automation.Peers.ItemAutomationPeer.GetNameCore()
  at System.Windows.Automation.Peers.AutomationPeer.UpdateSubtree()
  at System.Windows.Automation.Peers.AutomationPeer.UpdateSubtree()
  at System.Windows.Automation.Peers.AutomationPeer.UpdateSubtree()
  at System.Windows.ContextLayoutManager.fireAutomationEvents()
  at System.Windows.ContextLayoutManager.UpdateLayout()
  at System.Windows.ContextLayoutManager.UpdateLayoutCallback(Object arg)
  at System.Windows.Media.MediaContext.InvokeOnRenderCallback.DoWork()
  at System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks()
  at System.Windows.Media.MediaContext.RenderMessageHandlerCore(Object    resizedCompositionTarget)
  at System.Windows.Media.MediaContext.AnimatedRenderMessageHandler(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)
  at System.Windows.Threading.DispatcherOperation.InvokeImpl()
  at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
  at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
  at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
  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.LegacyInvokeImpl(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.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
  at System.Windows.Threading.Dispatcher.Run()
  at System.Windows.Application.RunDispatcher(Object ignore)
  at System.Windows.Application.RunInternal(Window window)
  at System.Windows.Application.Run(Window window)
  at System.Windows.Application.Run()

【问题讨论】:

  • 当您说这发生在 Windows-8 测试机器上时,该应用程序是在同一台机器上构建的还是在 Windows-8 机器上构建的?或者它是建立在 W7 上并刚刚从 Windows-8 执行的?认为两个操作系统之间的 dll 之间存在相当多的不匹配,并且需要在本地复制一些引用,以便它在从 W7 机器构建时在 Windows-8 上工作。尝试从 Windows-8 构建它,看看问题是否仍然存在。完成后您可能会看到编译错误或获得一些内部异常详细信息,这可能表明哪个 dll 导致了不匹配(例如 Aero 与 Aero2 等)
  • 这是一个有趣的想法。我没有带 VS 的 Windows 8 机器,所以我现在无法测试这个假设。但是,您可能会注意到框架略有不同。

标签: wpf windows-8 datagrid


【解决方案1】:

通过打开讲述人并在使用虚拟化并将 VirtualizationMode 设置为 Recycling 的树视图中滚动,对我来说这个问题可以可靠地重现。将其设置为标准会导致性能受到非常轻微的影响,但不再发生崩溃。

【讨论】:

    【解决方案2】:

    【讨论】:

      【解决方案3】:

      我选择捕获错误并将其作为“非致命”错误处理。

      private void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
      {
          if (e.Exception.Source?.ToString() == "PresentationFramework")
          {
              e.Handled = true;
              Postgres.LogException(e.Exception, false);
              return;
          }
      
          HandleException(e.Exception);
          e.Handled = true;
          Shutdown();
      }
      

      【讨论】:

        【解决方案4】:

        在与远程调试器反复多次,以及几乎没有结果的在线搜索之后,我能够将问题追溯到几个行为不端的 ItemAutomationPeer 实例。

        当我遇到这个问题时,我对 UI 自动化 以及它在 WPF 框架中的支持方式一无所知。事实上,当 AutomationPeer 出于某种原因让我想到 COM 互操作时,我一度追问了错误的问题。如果您正在阅读本文并且不知道 UI 自动化可能是什么,herehere 可能会让您了解 UI 自动化在 WPF 上下文中的含义。

        就我而言,事实证明,应用程序在 Windows 8 测试机器上崩溃但在我的开发机器(以及它已部署到的无数其他计算机)上运行良好的原因是 Windows 8机器运行了某种 UI 可访问性应用程序(或其他一些 UI 自动化客户端)。在我的 Windows 7 开发机器上启动讲述人应用程序后,我就可以让应用程序崩溃。

        一旦我了解了根本问题,我仍然无法进一步调试它以准确找出导致问题的控件,但更多在线阅读似乎指向自定义控件的大致方向,因此我开始了消除过程以确定哪些自定义 WPF 控件有罪。我找到了两个自定义控件 - 一个扩展了 DataGrid,另一个扩展了 ListBox。

        最后,我的问题的解决方案是创建扩展ItemsControlAutomationPeer 基类的自定义类,并通过覆盖OnCreateAutomationPeer 方法在每个有问题的自定义控件上提供这些作为自动化对等点。

        protected override AutomationPeer OnCreateAutomationPeer()
        {
            return new ControlSpecificCustomAutomationPeer(this);
        }
        

        ControlSpecificCustomAutomationPeer 类至少看起来像这样:

        public class ControlSpecificCustomAutomationPeer
            : ItemsControlAutomationPeer
        {
            public ControlSpecificCustomAutomationPeer(ItemsControl owner)
                : base(owner)
            {
            }
        
            protected override string GetNameCore()
            {
                return "";                         // return something meaningful here..
            }
        
            protected override ItemAutomationPeer CreateItemAutomationPeer(object item)
            {
                return new CustomDummyItemAutomationPeer(item, this);
            }             
        }
        
        public class CustomDummyItemAutomationPeer
            : System.Windows.Automation.Peers.ItemAutomationPeer
        {
            public CustomDummyItemAutomationPeer(object item, ItemsControlAutomationPeer itemsControlAutomationPeer)
                : base(item, itemsControlAutomationPeer)
            {
            }
        
            protected override string GetNameCore()
            {
                if (Item == null)
                    return "";            
        
                return Item.ToString() ?? "";
            }
        
            protected override AutomationControlType GetAutomationControlTypeCore()
            {
                return System.Windows.Automation.Peers.AutomationControlType.Text;
            }
        
            protected override string GetClassNameCore()
            {
                return "Dummy";
            }
        }
        

        【讨论】:

        • 谢谢你,这是救命的!
        • @NS.X。 - 我打赌..我知道我浪费了大量时间来追逐这个。
        • 对于它的价值,我们遇到了同样的问题,但只有当应用程序在 Win8 上运行或我们在 Win7 中打开讲述人时。事实证明,我们的交互是各种属性设置器之间难以调试的交互。设置属性后,在该代码的某处,我们将其设置回 null。在我诊断之前,我发现上述解决方案“修复”了自动化对等症状。
        • 当我在 DataGrid 中留下已编辑的行而不按 Enter 按钮,但通过单击另一行时,我发现了这个问题。这个修复对我有用,问题现在消失了。
        猜你喜欢
        • 1970-01-01
        • 2015-05-20
        • 1970-01-01
        • 1970-01-01
        • 2015-07-14
        • 1970-01-01
        • 2018-02-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多