我正在使用一个奇怪的NullReferenceException,它显然是从GetNameCore()类的ItemAutomationPeer函数触发的。
异常的详细信息如下,但真正有趣的方面是它不会出现在运行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()
答案 0 :(得分:13)
经过远程调试器的大量反复,以及几乎无效的在线搜索后,我能够将问题追踪到几个行为不端的ItemAutomationPeer个实例。
当我遇到这个问题时,我对 UI Automation 及其在WPF框架中的支持方面一无所知。事实上,当 AutomationPeer 由于某种原因让我想到COM互操作时,我一会儿就追错了问题。如果您正在阅读本文并且不知道可能启动的UI自动化here和here可能会让您了解UI自动化在WPF上下文中的含义。
在我的情况下,事实证明应用程序在Windows 8测试计算机上崩溃但它在我的开发机器上工作正常(以及它已被部署到的无数其他计算机)的原因是Windows 8机器运行某种UI辅助功能应用程序(或其他一些UI自动化客户端)。一旦我在Windows 7开发机器上启动了Narrator应用程序,我就能让应用程序崩溃一样..
一旦我理解了根问题,我仍然无法进一步调试这个以确切地找出导致问题的控件,但更多在线阅读似乎指向自定义控件的大致方向,因此我开始了一个消除过程确定哪些自定义WPF控件有罪。我发现了两个自定义控件 - 一个扩展了DataGrid,另一个扩展了ListBox。
最后,我的问题的解决方案是创建扩展ItemsControlAutomationPeer基类的自定义类,并通过覆盖{{3}在每个自定义控件上提供这些自定义控件的问题。方法。
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";
}
}
答案 1 :(得分:1)
仅供参考,此错误将在将来的.Net 4.8版本中修复。 https://developercommunity.visualstudio.com/content/problem/575165/vs-1604-ide-crash-argumentnullexception.html
答案 2 :(得分:0)
我选择捕获错误并将其作为“非致命”错误进行处理。
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();
}
答案 3 :(得分:0)
对我来说,此问题可以通过打开“讲述人”并在使用VirtualizationMode设置为“ Recycling”的虚拟化的树状视图中滚动来可靠地重现。将其设置为“标准”对性能的影响很小,但是崩溃不再发生。