Our clients are seeing an occasional application crash after ProcessAsyncInvalidations() / ProcessAsyncInvalidationsImpl() are called from within the framework. The stack at the time is as follows:
[[HelperMethodFrame_1OBJ] (System.Environment.FailFast)] System.Environment.FailFast(System.String) WindowsBase_ni!MS.Internal.Invariant.FailFast(System.String, System.String)+35 WindowsBase_ni!MS.Internal.Invariant.Assert(Boolean, System.String)+272185 PresentationFramework_ni!System.Windows.Window.GetWindowMinMax()+51 PresentationFramework_ni!System.Windows.Window.MeasureOverride(System.Windows.Size)+4d PresentationFramework_ni!System.Windows.FrameworkElement.MeasureCore(System.Windows.Size)+585 PresentationCore_ni!System.Windows.UIElement.Measure(System.Windows.Size)+1cc PresentationCore_ni!System.Windows.ContextLayoutManager.UpdateLayout()+1a1 PresentationCore_ni!System.Windows.UIElement.UpdateLayout()+14 Infragistics.Windows.DataPresenter.GridUtilities.ProcessAsyncInvalidationsImpl()+104 Infragistics.Windows.DataPresenter.GridUtilities.ProcessAsyncInvalidations()+a [[HelperMethodFrame_PROTECTOBJ] (System.RuntimeMethodHandle.InvokeMethod)] System.RuntimeMethodHandle.InvokeMethod(System.Object, System.Object[], System.Signature, Boolean) [[DebuggerU2MCatchHandlerFrame]] mscorlib_ni!System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(System.Object, System.Object[], System.Object[])+c1 mscorlib_ni!System.Reflection.RuntimeMethodInfo.UnsafeInvoke(System.Object, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo)+67 mscorlib_ni!System.Delegate.DynamicInvokeImpl(System.Object[])+69 WindowsBase_ni!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate, System.Object, Int32)+ad WindowsBase_ni!MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(System.Object, System.Delegate, System.Object, Int32, System.Delegate)+3a WindowsBase_ni!System.Windows.Threading.DispatcherOperation.InvokeImpl()+ac WindowsBase_ni!System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(System.Object)+38 mscorlib_ni!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)+a7 mscorlib_ni!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)+16 mscorlib_ni!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)+41 WindowsBase_ni!System.Windows.Threading.DispatcherOperation.Invoke()+5b WindowsBase_ni!System.Windows.Threading.Dispatcher.ProcessQueue()+16b WindowsBase_ni!System.Windows.Threading.Dispatcher.WndProcHook(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef)+5a WindowsBase_ni!MS.Win32.HwndWrapper.WndProc(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef)+9b WindowsBase_ni!MS.Win32.HwndSubclass.DispatcherCallbackOperation(System.Object)+6b WindowsBase_ni!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate, System.Object, Int32)+52 WindowsBase_ni!MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(System.Object, System.Delegate, System.Object, Int32, System.Delegate)+3a WindowsBase_ni!System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority, System.TimeSpan, System.Delegate, System.Object, Int32)+10e WindowsBase_ni!MS.Win32.HwndSubclass.SubclassWndProc(IntPtr, Int32, IntPtr, IntPtr)+f1 WindowsBase_ni!DomainNeutralILStubClass.IL_STUB_PInvoke(System.Windows.Interop.MSG ByRef)+3c [[InlinedCallFrame]] WindowsBase_ni!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame)+b1 WindowsBase_ni!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame)+49 WindowsBase_ni!System.Windows.Threading.Dispatcher.Run()+4b RCS.ZettaUI.ControlHost+<>c__DisplayClass6.a()+5d6 mscorlib_ni!System.Threading.ThreadHelper.ThreadStart_Context(System.Object)+6f mscorlib_ni!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)+a7 mscorlib_ni!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)+16 mscorlib_ni!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)+41 mscorlib_ni!System.Threading.ThreadHelper.ThreadStart()+44
No, I can’t regularly replicate the crash. Do you have any ideas why GridUtilities. ProcessAsyncInvalidations() / ProcessAsyncInvalidationsImpl() would cause the entire application to crash?
ThanksDan
Hi Dan,
It shouldn't cause any issues. I'm pretty confident that ProcessCellInvalidationsSynchronously will keep the issue from happening based on the dmp file you sent. The application is definitely crashing because the window was disposed in the middle of ProcessAsyncInvalidations which ended up setting the internal IsCompositionTargetInvalid property to true.
Let me know how it turns out after you implement these changes.
Rob,
We do have some windows contained within a HwndHost where when the host is closed, we close the core window. But the user claims they were not interacting with the UI at the time of the failure. However, I can add your recommended push frame there if you think it won’t hurt anything else. I can also add a configuration file option to set ProcessCellInvalidationsSynchronously to true and see if it helps.
Thanks
Dan
No worries. I brought this issue up with our developers and they explained how that ProcessAsyncInvalidations method works. It is an optimization we made in order to not bog down the .Net framework by dirtying its layout manager for each element the DataPresenter might be touching.
So the main issue behind your crash is that your window was closed while the ProcessAsyncInvalidations() was in the middle of doing it's thing. When the window is closed it no longer has a composition target and when ProcessAsyncInvalidations() finally got around to calling UpdateLayout() it called Environment.FailFast() which stopped the application. You can confirm this by opening the dump file you sent me and checking your window's IsDisposed property in the watch window. It's set to true.
In your application, are there instances where you are opening and closing windows automatically? If so you may want to invoke an UpdateLayout on the window before you close it. Or you can otherwise force the dispatcher to process its queue - e.g. creating a frame, pusing it in and waiting for it.
DispatcherFrame f = new DispatcherFrame();Dispatcher.CurrentDispatcher.BeginInvoke(priority, (SendOrPostCallback)delegate(object arg){ DispatcherFrame fr = arg as DispatcherFrame; fr.Continue = false;}, f);Dispatcher.PushFrame(f);
Another option you have is to set the ProcessCellInvalidationsSynchronously static property so they aren't processed asynchronously anymore.
Hi Rob,
That is very interesting.
From what the user tells me, they were not interacting with the software at the time of the failure. Our software is used for automation, and constantly updates information to the user as things change. These updates are many, and unpredictable. So it’s hard to say exactly what is going on. We do use your grids which could be automatically scrolled by the system, or simply have its data refreshed at any time. For efficiency, we thread background processes when necessary and update the UI via dispatchers. I know this is vague, but that’s all I’m getting from our users. I’ll ask them again to see if they have seen the problem since, and what they were doing at the time.
Thanks for the dump file. I loaded the PDBs for some of those System.Windows calls at the top of the call stack and I was able to see what causes the FailFast() call to occur. I have not figured out why yet.
It crashes because the window (RCS.ZettaUI.HostWindow) has an invalid composition target. The Window class has a property called IsCompositionTargetInvalid and this is returning true. Since this is true, when it gets to the GetWindowMinMax() call it asserts which then triggers the FailFast() call. Here is the assert:
internal virtual WindowMinMax GetWindowMinMax() { WindowMinMax mm = new WindowMinMax( ); Invariant.Assert(IsCompositionTargetInvalid == false, "IsCompositionTargetInvalid is supposed to be false here");
So we now know that the window doesn't have a valid composition target. What we don't know is why it is invalid and what is triggering the ProcessAsyncInvalidations() method in the first place.
Are you able to provide any details about what your customers were doing when the crash occurred? Was there a series of steps that they remember taking which led up to the crash? Even if the steps don't always reproduce the issue, it might help in figuring out why ProcessAsyncInvalidations() is being called.