WPF应用程序随OOM异常随机崩溃

时间:2014-08-27 14:26:43

标签: c# wpf multithreading out-of-memory prism

我一直在处理这个问题。有时会抛出无效的操作异常,有时内存不足。随机用户可以在一天内运行数天并多次崩溃。

我从一个用户那里获得了调用堆栈,并且无法理解可能导致此问题的原因。它是一个具有丰富UI的WPF应用程序。很多观点,清单。使用PRISM和区域。

它还使用后台线程来侦听TCP,刷新数据并在UI线程上发送PRISM通知进行更新。这个堆栈是否提供了我可能需要检查的线索?它不是源于我的代码..

  

在   MS.Utility.ArrayItemList 1[[System.Windows.Freezable+FreezableContextPair, WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]..ctor(Int32) at MS.Utility.FrugalObjectList 1 [[System.Windows.Freezable + FreezableContextPair,   WindowsBase,Version = 4.0.0.0,Culture = neutral,   PublicKeyToken = 31bf3856ad364e35]] .set_Capacity(Int32)at   MS.Utility.FrugalObjectList`1 [[System.Windows.Freezable + FreezableContextPair,   WindowsBase,Version = 4.0.0.0,Culture = neutral,   PublicKeyToken = 31bf3856ad364e35]]。插入(Int32,FreezableContextPair)   在   System.Windows.Freezable.AddContextToList(System.Windows.DependencyObject,   System.Windows.DependencyProperty)at   System.Windows.Freezable.AddContextInformation(System.Windows.DependencyObject,   System.Windows.DependencyProperty)at   System.Windows.Freezable.AddInheritanceContext(System.Windows.DependencyObject,   System.Windows.DependencyProperty)at   System.Windows.DependencyObject.ProvideSelfAsInheritanceContext(System.Windows.DependencyObject,   System.Windows.DependencyProperty)at   System.Windows.Freezable.OnFreezablePropertyChanged(System.Windows.DependencyObject,   System.Windows.DependencyObject,System.Windows.DependencyProperty)
  在   System.Windows.Media.RenderData.PropagateChangedHandler(System.EventHandler,   布尔)   System.Windows.UIElement.RenderClose(System.Windows.Media.IDrawingContent)   在   System.Windows.Media.VisualDrawingContext.CloseCore(System.Windows.Media.RenderData)   在System.Windows.Media.RenderDataDrawingContext.DisposeCore()at   System.Windows.Media.DrawingContext.System.IDisposable.Dispose()at   System.Windows.Media.RenderDataDrawingContext.Close()at   System.Windows.UIElement.Arrange(System.Windows.Rect)at   System.Windows.Controls.DataGridCellsPanel.ArrangeChild(System.Windows.UIElement,   Int32,ArrangeState)at   System.Windows.Controls.DataGridCellsPanel.ArrangeOverride(System.Windows.Size)   在System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect)
  在System.Windows.UIElement.Arrange(System.Windows.Rect)处   MS.Internal.Helper.ArrangeElementWithSingleChild(System.Windows.UIElement,   System.Windows.Size)at   System.Windows.Controls.ItemsPresenter.ArrangeOverride(System.Windows.Size)   在System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect)
  在System.Windows.UIElement.Arrange(System.Windows.Rect)处   System.Windows.Controls.Control.ArrangeOverride(System.Windows.Size)
  在   System.Windows.Controls.Primitives.DataGridCellsPresenter.ArrangeOverride(System.Windows.Size)   在System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect)
  在System.Windows.UIElement.Arrange(System.Windows.Rect)处   System.Windows.Controls.Grid.ArrangeOverride(System.Windows.Size)
  在System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect)
  在System.Windows.UIElement.Arrange(System.Windows.Rect)处   System.Windows.Controls.Border.ArrangeOverride(System.Windows.Size)
  在System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect)
  在System.Windows.UIElement.Arrange(System.Windows.Rect)处   System.Windows.Controls.Control.ArrangeOverride(System.Windows.Size)
  在   System.Windows.Controls.DataGridRow.ArrangeOverride(System.Windows.Size)   在System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect)
  在System.Windows.UIElement.Arrange(System.Windows.Rect)处   System.Windows.Controls.VirtualizingStackPanel.ArrangeOtherItemsInExtendedViewport(布尔,   System.Windows.UIElement,System.Windows.Size,Double,Int32,   System.Windows.Rect ByRef,System.Windows.Size ByRef,   System.Windows.Point ByRef,Int32 ByRef)at   System.Windows.Controls.VirtualizingStackPanel.ArrangeOverride(System.Windows.Size)   在System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect)
  在System.Windows.UIElement.Arrange(System.Windows.Rect)处   System.Windows.ContextLayoutManager.UpdateLayout()at   System.Windows.ContextLayoutManager.UpdateLayoutCallback(System.Object的)   在System.Windows.Media.MediaContext + InvokeOnRenderCallback.DoWork()
  在System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks()
  在   System.Windows.Media.MediaContext.RenderMessageHandlerCore(System.Object的)   在   System.Windows.Media.MediaContext.RenderMessageHandler(System.Object的)   在   System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate,   System.Object,Int32)at   MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(System.Object的,   System.Delegate,System.Object,Int32,System.Delegate)at   System.Windows.Threading.DispatcherOperation.InvokeImpl()at   System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(System.Object的)   在   System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext,   System.Threading.ContextCallback,System.Object,Boolean)at   System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext,   System.Threading.ContextCallback,System.Object,Boolean)at   System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext,   System.Threading.ContextCallback,System.Object)at   System.Windows.Threading.DispatcherOperation.Invoke()at   System.Windows.Threading.Dispatcher.ProcessQueue()at   System.Windows.Threading.Dispatcher.WndProcHook(IntPtr,Int32,IntPtr,   Int.Ptr,布尔ByRef)在MS.Win32.HwndWrapper.WndProc(IntPtr,   Int32,IntPtr,IntPtr,Boolean ByRef)at   MS.Win32.HwndSubclass.DispatcherCallbackOperation(System.Object)at at   System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate,   System.Object,Int32)at   MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(System.Object的,   System.Delegate,System.Object,Int32,System.Delegate)at   System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority,   System.TimeSpan,System.Delegate,System.Object,Int32)at   MS.Win32.HwndSubclass.SubclassWndProc(IntPtr,Int32,IntPtr,IntPtr)
  在   MS.Win32.UnsafeNativeMethods.DispatchMessage(System.Windows.Interop.MSG   ByRef)at   System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame)   在   System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame)   在System.Windows.Threading.Dispatcher.Run()处   System.Windows.Application.RunDispatcher(System.Object)at   System.Windows.Application.RunInternal(System.Windows.Window)at   System.Windows.Application.Run(System.Windows.Window)at   ArturExpress.Main.App.Main()

2 个答案:

答案 0 :(得分:1)

从这个堆栈跟踪可以确定的是内存不足异常发生在StackPanel的UpdateLayout期间,其中包含DataGrid等。

当要求其中一个DataGrid行重新排列时,其中一个看起来像是冻结列的单元格(似乎包含一个面板)最终会从Frozen冻结到Unfrozen(反之亦然) )在尝试构造FreezableContextPair对象时,发生了内存不足异常。

如果没有额外的数据点,这是巧合还是因果关系是不可能的。换句话说,如果另外10个堆栈跟踪显示完全相同的跟踪,那么它可能是一个特定的事件集,这些事件与您的一个网格有一个从freezable到freegreable的列,由于某种原因导致内存不足异常。 / p>

如果其他堆栈跟踪显示完全不同的结果,则此特定异常可能是巧合,例如有些东西把内存使用推到了边缘,而这个特殊的操作碰巧是把它推到了边缘。

您需要更多的数据点来确定,并且应该让用户在发生这种情况时开始发送堆栈跟踪+在内存分析器中运行应用程序以查看是否可以看到任何异常。

答案 1 :(得分:1)

set_Capacity通常会导致尝试分配连续的内存块。如果它足够大,它将从未压缩的大对象堆中请求,因此碎片可能使得难以找到连续的存储器块以满足请求。

内存分析器将是我的下一步,但如果你得到其他类型的异常,那么记录会更好。

对于桌面应用程序,我使用log4net和内存记录器,其中包含最近500条消息的详细信息日志。如果发生异常,我会将其指向文件,这样我就可以非常详细地了解导致异常的情况。

注意调整某些集合的容量通常需要3倍于生成阵列所需的内存。这是因为当它们超过当前容量时,它们会分配两倍于当前大小的新阵列,并将现有项目复制到新阵列。因此,在此转换期间,集合需要3倍的内存,当前数组被复制,并且要复制的数组大两倍。我不知道这是不是在这里发生了什么。当阵列的容量经常增长时,您通常会在内存配置文件中看到锯齿模式不断增加。