16

我正在与一个奇怪的 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()
4

4 回答 4

19

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

当我遇到这个问题时,我对UI 自动化以及 WPF 框架如何支持它的知识为零。事实上,当AutomationPeer出于某种原因让我想到 COM 互操作时,我一度追问了错误的问题。如果您正在阅读本文并且不知道 UI 自动化可能从这里开始,这里可能会让您了解 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";
    }
}
于 2013-04-27T20:49:50.067 回答
3

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

于 2020-04-21T16:37:34.133 回答
1

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

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();
}
于 2019-02-13T20:19:04.843 回答
1

仅供参考,此错误将在 .Net 4.8 的未来版本中修复。 https://developercommunity.visualstudio.com/content/problem/575165/vs-1604-ide-crash-argumentnullexception.html

于 2019-07-02T08:27:56.513 回答