我们有一个大型的WPF应用程序,每天使用多个小时,可能需要200-500 MB或更多的内存。偶尔,应用程序会无缘无故地挂起。分析进程转储显示垃圾收集正在进行,并且是暂停应用程序的原因。
我们使用.NET 4.0,并且据我所知,新引入的“background garbage collection”应该减少整个进程被垃圾收集(前台垃圾收集)阻塞的时间。
然而,即使这些暂停不那么频繁,当它们超过几秒钟时(这是情况),它们也会打断工作流程。
这引导我提出以下问题:
我们使用.NET 4.0,并且据我所知,新引入的“background garbage collection”应该减少整个进程被垃圾收集(前台垃圾收集)阻塞的时间。
然而,即使这些暂停不那么频繁,当它们超过几秒钟时(这是情况),它们也会打断工作流程。
这引导我提出以下问题:
我读到在服务器环境中,默认情况下不使用后台垃圾回收。我们的应用程序确实在服务器操作系统上运行(Windows Server 2003 R2 x64),尽管它是客户端应用程序(而不是服务器应用程序)。这是否意味着不使用后台垃圾回收?或者它只适用于服务/ASP.NET?
假设确实启用了后台垃圾回收,如何防止前台回收发生得太频繁/时间过长?我的当前方法是检测应用程序的空闲期间(例如,应用程序未使用5分钟或更长时间),并启动强制垃圾回收,以便在应用程序被使用时不会在以后的某个时间发生。
Debug Diag进程转储信息:
堆栈跟踪:
mscorlib_ni!System.GC.Collect(Int32, System.GCCollectionMode)+47
[[InlinedCallFrame] (System.GC._Collect)] System.GC._Collect(Int32, Int32)
PresentationCore_ni!MS.Internal.MemoryPressure.ProcessAdd()+1d0
PresentationCore_ni!MS.Internal.MemoryPressure.Add(Int64)+39
PresentationCore_ni!System.Windows.Media.SafeMILHandleMemoryPressure..ctor(Int64)+43
PresentationCore_ni!System.Windows.Media.SafeMILHandle.UpdateEstimatedSize(Int64)+38
PresentationCore_ni!System.Windows.Media.Imaging.RenderTargetBitmap.FinalizeCreation()+df
PresentationCore_ni!System.Windows.Media.Imaging.RenderTargetBitmap..ctor(Int32, Int32, Double, Double, System.Windows.Media.PixelFormat)+d9
WindowsFormsIntegration_ni!System.Windows.Forms.Integration.HostUtils.GetRenderTargetBitmapForVisual(Int32, Int32, System.Windows.Media.Visual)+b1
WindowsFormsIntegration_ni!System.Windows.Forms.Integration.HostUtils.GetBitmapForFrameworkElement(System.Windows.FrameworkElement)+89
WindowsFormsIntegration_ni!System.Windows.Forms.Integration.HostUtils.GetBitmapForTransparentWindowsFormsHost(System.Windows.Forms.Integration.WindowsFormsHost)+4b
WindowsFormsIntegration_ni!System.Windows.Forms.Integration.HostUtils.GetBitmapForWindowsFormsHost(System.Windows.Forms.Integration.WindowsFormsHost, System.Windows.Media.Brush)+1f
WindowsFormsIntegration_ni!System.Windows.Forms.Integration.WindowsFormsHostPropertyMap.BackgroundPropertyTranslator(System.Object, System.String, System.Object)+109
WindowsFormsIntegration_ni!System.Windows.Forms.Integration.PropertyMap.RunTranslator(System.Windows.Forms.Integration.PropertyTranslator, System.Object, System.String, System.Object)+32
WindowsFormsIntegration_ni!System.Windows.Forms.Integration.WindowsFormsHost.ArrangeOverride(System.Windows.Size)+277
PresentationFramework_ni!System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect)+8e3
PresentationCore_ni!System.Windows.UIElement.Arrange(System.Windows.Rect)+385
PresentationCore_ni!System.Windows.ContextLayoutManager.UpdateLayout()+2b5
PresentationCore_ni!System.Windows.ContextLayoutManager.UpdateLayoutCallback(System.Object)+19
PresentationCore_ni!System.Windows.Media.MediaContext+InvokeOnRenderCallback.DoWork()+10
PresentationCore_ni!System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks()+76
PresentationCore_ni!System.Windows.Media.MediaContext.RenderMessageHandlerCore(System.Object)+8a
PresentationCore_ni!System.Windows.Media.MediaContext.AnimatedRenderMessageHandler(System.Object)+6e
WindowsBase_ni!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate, System.Object, Int32)+53
WindowsBase_ni!MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(System.Object, System.Delegate, System.Object, Int32, System.Delegate)+42
WindowsBase_ni!System.Windows.Threading.DispatcherOperation.InvokeImpl()+8d
WindowsBase_ni!System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(System.Object)+38
mscorlib_ni!System.Threading.ExecutionContext.runTryCode(System.Object)+51
[[HelperMethodFrame_PROTECTOBJ] (System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup)] System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode, CleanupCode, System.Object)
mscorlib_ni!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)+6a
mscorlib_ni!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)+7e
mscorlib_ni!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)+2c
WindowsBase_ni!System.Windows.Threading.DispatcherOperation.Invoke()+68
WindowsBase_ni!System.Windows.Threading.Dispatcher.ProcessQueue()+15e
WindowsBase_ni!System.Windows.Threading.Dispatcher.WndProcHook(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef)+63
WindowsBase_ni!MS.Win32.HwndWrapper.WndProc(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef)+be
WindowsBase_ni!MS.Win32.HwndSubclass.DispatcherCallbackOperation(System.Object)+7d
WindowsBase_ni!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate, System.Object, Int32)+53
WindowsBase_ni!MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(System.Object, System.Delegate, System.Object, Int32, System.Delegate)+42
WindowsBase_ni!System.Windows.Threading.Dispatcher.InvokeImpl(System.Windows.Threading.DispatcherPriority, System.TimeSpan, System.Delegate, System.Object, Int32)+b4
WindowsBase_ni!MS.Win32.HwndSubclass.SubclassWndProc(IntPtr, Int32, IntPtr, IntPtr)+104
WindowsBase_ni!DomainBoundILStubClass.IL_STUB_PInvoke(System.Windows.Interop.MSG ByRef)+3c
[[InlinedCallFrame]]
WindowsBase_ni!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame)+c1
WindowsBase_ni!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame)+49
PresentationFramework_ni!System.Windows.Application.RunDispatcher(System.Object)+5b
PresentationFramework_ni!System.Windows.Application.RunInternal(System.Windows.Window)+74
PresentationFramework_ni!System.Windows.Application.Run(System.Windows.Window)+2b
MemoryPressure.Add
(一个 WPF 方法,而不是GC.AddMemoryPressure
)明确调用了GC.Collect(2)
- http://referencesource.microsoft.com/#PresentationCore/src/Core/CSharp/MS/Internal/MemoryPressure.cs。哎呀。可能在仅使用 WPF 和 GUI 时效果很好,但一旦开始在后台进行一些严肃的工作,它就会变得致命。 - LuaanGetBitmapForTransparentWindowsFormsHost
向下的链,并且在视图的布局期间避免GC,问题就会减轻。 - cod3monk3y