2014-08-27 96 views
0

我一直在處理這個很長一段時間。有時它會拋出無效的操作異常,有時會導致內存不足。隨機用戶可以在一天內多次運行並崩潰。WPF應用程序與OOM異常隨機崩潰

我得到了一個用戶的調用堆棧,並且無法理解可能導致此問題的原因。這是一個帶有豐富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,版本= 4.0.0.0,文化=中立, 公鑰= 31bf3856ad364e35 (Int32)at MS.Utility.FrugalObjectList` [[System.Windows.Freezable + FreezableContextPair, WindowsBase,Version = 4.0.0.0,Culture = neutral, PublicKeyToken = 31bf3856ad364e35]]。Insert(Int32, FreezableContextPair) at System.Windows.Freezable.AddContextToList(System.Windows.DependencyObject, System.Windows.De pendencyProperty)在 System.Windows.Freezable.AddContextInformation(System.Windows.DependencyObject, System.Windows.DependencyProperty)處 System.Windows.Freezable.AddInheritanceContext(System.Windows.DependencyObject, System.Windows.DependencyProperty) System.Windows.DependencyObject.ProvideSelfAsInheritanceContext(System.Windows.DependencyObject, System.Windows.DependencyProperty)在 System.Windows.Freezable.OnFreezablePropertyChanged(System.Windows.DependencyObject, System.Windows.DependencyObject,System.Windows.DependencyProperty)
at 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() System.Windows.Media.DrawingContext.System.IDisposable.Dispose()at System.Windows.Media.RenderDataDrawingContext.Close()at System.Windows.UIElement.Arrange(System.Windows.Rect )在 System.Windows.Controls.DataGridCellsPanel.ArrangeChild(System.Windows.UIElement, 的Int32,ArrangeState)在 System.Windows.Controls.DataGridCellsPanel.ArrangeOverride(System.Windows.Size) 在System.Windows.FrameworkElemen t.ArrangeCore(System.Windows.Rect)
at System.Windows.UIElement.Arrange(System.Windows.Rect)at MS.Internal.Helper.ArrangeElementWithSingleChild(System.Windows.UIElement, System.Windows.Size)在 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.FrameworkE lement.ArrangeCore(System.Windows。矩形)
在System.Windows.UIElement.Arrange(System.Windows.Rect)在 System.Windows.Controls.Grid.ArrangeOverride(System.Windows.Size)
在System.Windows.FrameworkElement.ArrangeCore(系統。 Windows.Rect)
在System.Windows.UIElement.Arrange(System.Windows.Rect)在 System.Windows.Controls.Border.ArrangeOverride(System.Windows.Size)
在System.Windows.FrameworkElement.ArrangeCore( System.Windows.Rect)
at System.Windows.UIElement.Arrange(System.Windows.Rect)at System.Windows.Controls.Control.ArrangeOverride(System.Windows.Size)
at System.Windows.Controls.DataGridRow.ArrangeOverride(System.Windows.Size) at System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect)
at System.Windows.UIElement.Arrange(System.Windows.Rect)在 System.Windows.Controls.VirtualizingStackPanel.ArrangeOtherItemsInExtendedViewport(布爾, System.Windows.UIElement,System.Windows.Size,雙,的Int32, System.Windows.Rect的ByRef,System.Windows.Size的ByRef, System.Windows .Point ByRef,Int32 ByRef)at System.Windows.Controls.VirtualizingStackPanel.ArrangeOverride(System.Windows.Size) at System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect)
at System.Windows.UIElement .Arrange(System.Windows.Rect)在 System.Windows.ContextLayoutManager.UpdateLayout()在 System.Windows.ContextLayoutManager.UpdateLayoutCallback(System.Object的) 在System.Windows.Media.MediaContext + InvokeOnRenderCallback.DoWork()
處 System.Windows.Media.MediaContext.RenderMessageHandler(System.Object的)System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks()
在 System.Windows.Media.MediaContext.RenderMessageHandlerCore(System.Object的) 在 MS.Intern。System.InWindows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate, System.Object,Int32)at al.Threading.ExceptionFilterHelper.TryCatchWhen(System.Object的, System.Delegate,System.Object的,的Int32,System.Delegate)在 System.Windows.Threading.DispatcherOperation.InvokeImpl()在 System.Windows.Threading.DispatcherOperation。 InvokeInSecurityContext(System.Object的) 處 System.Threading.ExecutionContext.Run(的System.Threading System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback,System.Object的,布爾值)。 ExecutionContext, System.Threading.ContextCallback,System.Object,Boolean) System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback,System.Object)at System.Windows.Threading.DispatcherOperation.Invoke()在 System.Windows.Threading.Dispatcher.ProcessQueue()在 System.Windows.Threading.Dispatcher.WndProcHook(IntPtr的,的Int32,IntPtr的, IntPtr的,布爾的ByRef)在MS.Win32.HwndWrapper.WndProc(IntPtr, Int32,IntPtr,IntPtr,Boolean ByRef)at MS.Win32.HwndSubclass.DispatcherCallbackOperation(System.Object)at System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate, System.Object的,Int32)將在在 System.Windows.Threading.Dispatcher.LegacyInvokeImpl MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(System.Object的, System.Delegate,System.Object的,的Int32,System.Delegate)( System.Windows。Threading.DispatcherPriority, System.TimeSpan,System.Delegate,System.Object的,Int32)將在 MS.Win32.HwndSubclass.SubclassWndProc(IntPtr的,的Int32,IntPtr的,IntPtr的)
在 MS.Win32.UnsafeNativeMethods.DispatchMessage(系統.Windows.Interop.MSG 的ByRef)在 System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame) 在 System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame) at System.Windows.Threading.Dispatcher.Run()at System.Windows.Application.RunDispatcher(System.Object)at System.Windows.Application.RunInternal(System.Windows.Window)at System.Windows.Application.Run(System.Windows.Window)在 ArturExpress.Main.App.Main()

+0

我建議使用一些分析器來查看實際發生的事情。從描述中很難猜出... – walther 2014-08-27 14:34:04

+0

堆棧跟蹤的實際異常是什麼?是OutOfMemoryException還是別的?另外,有沒有內部的例外? – user469104 2014-08-27 14:35:09

+0

不幸的是我無法追查它。這是不可複製的,隨機發生在用戶機器上(可以好幾天)。該堆棧跟蹤來自事件日誌。這是OutOfMemoryException。 – katit 2014-08-27 14:41:37

回答

1

有一個set_Capacity通常會導致嘗試分配連續的內存塊。如果它足夠大,將從大型對象堆中請求,而這個堆沒有壓縮,因此碎片會導致難以找到連續的內存塊來滿足請求。

內存分析器將是我的下一步,但如果您正在獲取其他類型的異常,那麼日誌記錄會更好。

對於桌面應用程序,我將log4net與內存記錄器一起使用,其中包含最近500條消息的詳細信息日誌。如果發生異常,我會把它指向一個文件,這樣我就會有一個非常詳細的上下文導致異常。

注意調整某些集合的容量通常需要增長陣列所需內存的3倍。這是因爲,當它們超過當前容量時,它們會分配一個兩倍於當前大小的新數組,並將現有項目複製到新數組中。因此,在此過渡期間,集合需要3倍的內存,當前陣列正在從中複製,而兩倍大的陣列將被複制到內存中。我不知道這是不是在這裏發生。當您的陣列容量經常增長時,您通常會在內存配置文件中看到一個漸增的鋸齒圖案。

+0

嗯..列表不大,也許是400個項目。通過移除插入來更新項目(這是讓可觀察數組工作的最佳方式),但沒有什麼超級瘋狂。我使用內存分析器進行了本地測試,沒有發生任何奇怪的事情一切都很正常,我甚至做了一些壓力測試,發現異常的高負載(甚至接近真實),並且內存飆升,但在GC進入後卻下降了。 – katit 2014-08-27 15:14:28

+0

像用戶一樣嘗試幾個小時,看它是否逐步使用更多的記憶。如果有泄漏,你會開始看到每次GC啓動後,它不會下降。如果正在引用不再需要的對象,則可以在C#中獲得「泄漏」。即您從一個列表中刪除項目,但它們仍然在內部從UI框架引用。無論是大量的測試還是增加詳細的日誌記錄來試圖確定問題出現的情況。否則,我們在黑暗中拍攝。 – AaronLS 2014-08-27 15:25:42

+0

是的,我知道..我確實監控了一天的應用程序。沒什麼奇怪的用戶不會整體抱怨。有70個用戶,偶爾有一個用戶開始抱怨崩潰。它就像這樣「最近工作的很好,本週它每天可能會崩潰一次,但是昨天我無法工作,因爲它一直在崩潰。」我是在指責線程代碼。審覈所有內容,隨處記錄錯誤。沒有結果... – katit 2014-08-27 15:28:20

1

我們可以從這個堆棧跟蹤確定的是,內存溢出異常期間發生一個StackPanel的UpdateLayout,其中包含一個DataGrid。

當其中一個DataGrid行被要求重新排列自己時,看起來是凍結列的一部分的一個單元格(似乎包含一個面板)最終要麼從凍結到未凍結相反),此時嘗試構建FreezableContextPair對象時發生內存不足異常。

無論這是否是巧合還是因果關係都不可能說沒有額外的數據點。換句話說,如果有10個棧跟蹤顯示完全相同的跟蹤,那麼它可能是一組特定的事件,與您的某個網格有一列從凍結到不可解凍,出於某種原因會導致內存不足異常。

如果其他堆棧跟蹤顯示完全不同的結果,那麼這個特定的例外可能是巧合的,例如,一些東西將內存使用推到了邊緣,而這種特殊的操作恰好是把它推到邊緣的那個。

您需要更多的數據點來確定並且應該要求您的用戶在發生這種情況時開始發送堆棧跟蹤+在內存分析器中運行應用程序以查看是否可以看到任何異常。

相關問題