C#系统组件.Win32异常(0x80004005):没有足够的存储空间来处理此命令。

4

运行我的应用程序 (.Net 4.5, 64位, WPF) 长时间(一到两周)后,我遇到了以下应用程序崩溃:

Faulting application name: XY.exe, Version: 2.12.2.2, Time: 0x5bade142
Faulting module name: KERNELBASE.dll, Version: 6.1.7601.24150, Time: 0x5b0cbc65
Exception code: 0xe0434352
Fault offset: 0x000000000001a06d
Faulting process id: 0x8694
Faulting application start time: 0x01d457228a130410
Faulting application path: C:\Testsysteme\YY.exe
Faulting module path: C:\Windows\system32\KERNELBASE.dll
Report Id: dbfc630b-c61f-11e8-bc27-1866da0d15ef

Application: XY.exe
Frameworkversion: v4.0.30319
Description: The process was terminated due to an unhandled exception
Exception information: System.ComponentModel.Win32Exception
at MS.Win32.UnsafeNativeMethods.RegisterClassEx(WNDCLASSEX_D)
at MS.Win32.HwndWrapper..ctor(Int32, Int32, Int32, Int32, Int32, Int32, Int32, System.String, IntPtr, MS.Win32.HwndWrapperHook[])
at System.Windows.Interop.HwndSource.Initialize(System.Windows.Interop.HwndSourceParameters)
at System.Windows.Interop.HwndSource..ctor(System.Windows.Interop.HwndSourceParameters)
at System.Windows.Controls.Primitives.Popup+PopupSecurityHelper.BuildWindow(Int32, Int32, System.Windows.Media.Visual, Boolean, System.Windows.Interop.HwndSourceHook, System.Windows.AutoResizedEventHandler)
at System.Windows.Controls.Primitives.Popup.BuildWindow(System.Windows.Media.Visual)
at System.Windows.Controls.Primitives.Popup.CreateWindow(Boolean)
at System.Windows.Controls.Primitives.Popup.OnIsOpenChanged(System.Windows.DependencyObject, System.Windows.DependencyPropertyChangedEventArgs)
at System.Windows.DependencyObject.OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs)
at System.Windows.FrameworkElement.OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs)
at System.Windows.DependencyObject.NotifyPropertyChange(System.Windows.DependencyPropertyChangedEventArgs)
at System.Windows.DependencyObject.UpdateEffectiveValue(System.Windows.EntryIndex, System.Windows.DependencyProperty, System.Windows.PropertyMetadata, System.Windows.EffectiveValueEntry, System.Windows.EffectiveValueEntry ByRef, Boolean, Boolean, System.Windows.OperationType)
at System.Windows.DependencyObject.SetValueCommon(System.Windows.DependencyProperty, System.Object, System.Windows.PropertyMetadata, Boolean, Boolean, System.Windows.OperationType, Boolean)
at System.Windows.Data.BindingOperations.SetBinding(System.Windows.DependencyObject, System.Windows.DependencyProperty, System.Windows.Data.BindingBase)
at System.Windows.Controls.Primitives.Popup.CreateRootPopup(System.Windows.Controls.Primitives.Popup, System.Windows.UIElement)
at System.Windows.Controls.ToolTip.OnIsOpenChanged(System.Windows.DependencyObject, System.Windows.DependencyPropertyChangedEventArgs)
at System.Windows.DependencyObject.OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs)
at System.Windows.FrameworkElement.OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs)
at System.Windows.DependencyObject.NotifyPropertyChange(System.Windows.DependencyPropertyChangedEventArgs)
at System.Windows.DependencyObject.UpdateEffectiveValue(System.Windows.EntryIndex, System.Windows.DependencyProperty, System.Windows.PropertyMetadata, System.Windows.EffectiveValueEntry, System.Windows.EffectiveValueEntry ByRef, Boolean, Boolean, System.Windows.OperationType)
at System.Windows.DependencyObject.SetValueCommon(System.Windows.DependencyProperty, System.Object, System.Windows.PropertyMetadata, Boolean, Boolean, System.Windows.OperationType, Boolean)
at System.Windows.DependencyObject.SetValue(System.Windows.DependencyProperty, System.Object)
at System.Windows.Controls.PopupControlService.RaiseToolTipOpeningEvent()
at System.Windows.Threading.DispatcherTimer.FireTick(System.Object)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate, System.Object, Int32)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(System.Object, System.Delegate, System.Object, Int32, System.Delegate)
at System.Windows.Threading.DispatcherOperation.InvokeImpl()
at 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 MS.Internal.CulturePreservingExecutionContext.Run(MS.Internal.CulturePreservingExecutionContext, 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, IntPtr, Boolean ByRef)
at 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)
at System.Windows.Threading.ExceptionWrapper.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)
at MS.Win32.UnsafeNativeMethods.DispatchMessage(System.Windows.Interop.MSG ByRef)
at System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame)
at System.Windows.Application.RunDispatcher(System.Object)
at System.Windows.Application.RunInternal(System.Windows.Window)
at XY.App.Main()

记录未处理异常的日志还显示:
System.ComponentModel.Win32Exception (0x80004005): Not enough storage is available to process this command

我已经找到了一个基本描述该问题的链接:connect.microsoft.com on web.archive.org,并且我下载并运行了来自JordiCorbilla/atom-table-monitor (GitHub)的AtomMonitor。事实上,我发现我的应用程序随着时间的推移创建了越来越多的RWM原子(在几天后大约达到了4000个),这与异常消息相符合。所有字符串看起来都像以下内容:

C1FE = HwndWrapper[XY.exe;;b68ce81a-d29f-414b-b63a-3b6979e33dd3]  --RWM

根据异常信息,我看到一个 'Popup' 在OnIsOpenChanged方法中调用了 RegisterClassEx

然而,在我的应用程序中打开和关闭多个弹出窗口并同时监视RWM原子的计数,我看不到任何增加,所以我找不到问题的确切来源。只是过了一段时间,再次查看统计数据时,我才发现数量增加了。

所以我的问题如下:

  1. 是否可以将 Popup 负责增加 RWM 原子的数量?如果是,这是一个错误吗?为什么它会创建一个新的 Window 并注册这些原子?

  2. 我是否错误地使用了 Popup?我需要关闭/释放某些内容吗?

  3. Popup 是否真的有问题?

  4. 应用程序创建或不应超过的 RWM 原子的“正常”数量是多少,因为据我所知它们无法删除?


这个问题很可能与C#或WPF无关,而是基于COM技术。作为.NET的前身,它有一些额外的问题和限制。我添加了这个标签来表示这一点。 - Christopher
@Christopher - System.ComponentModel是100% .net,除了名称之外与COM无关。此外,尽管您正确地指出错误来自本地环境(RegisterClassEx),但它不是COM,只是Windows。 - Simon Mourier
经过一些研究,我发现以下内容:它与弹出窗口或任何“真实”窗口无关。此外,关闭弹出窗口会释放原子表中的条目。我们在不同任务上创建WriteableBitmap进行图像处理。每当为此任务使用新线程(创建WPF控件)时,都会创建一个调度程序,该调度程序反过来创建一个HwndWrapper。如果不手动关闭调度程序,则不会释放这些资源。现在我们使用以下链接中的解决方法。除了WriteableBitmap之外,我们应该使用什么来在非UI线程上进行图像处理? - Creepin
更多细节请查看 https://github.com/tgjones/dynamic-image/issues/1 和 https://dev59.com/s2cs5IYBdhLWcg3wu2Up#12628379 以及 https://web.archive.org/web/20130727034302/https://connect.microsoft.com/VisualStudio/feedback/details/620588/system-componentmodel-win32exception-0x80004005-not-enough-storage-is-available-to-process-this-command - Creepin
在这个页面上也可以找到一个很好的解释:https://dev59.com/0Y7da4cB1Zd3GeqP_lJ2 - Creepin
显示剩余10条评论
1个回答

3
经过一些研究,我发现以下内容:这与弹出窗口或任何“真正”的窗口无关。此外,关闭弹出窗口会释放原子表中的条目。
原因是:我们在不同的任务上为图像处理创建可写位图。每当使用新线程执行此任务(创建WPF控件)时,都会创建一个Dispatcher,该Dispatcher又创建一个HwndWrapper。
如果不手动关闭Dispatcher,则不会释放这些资源。现在我们使用以下链接中的解决方法: GitHub: 当WPF耗尽内部资源时,抛出Win32Exception异常 SO: 为什么LongRunning任务(TPL)与JpegBitmapDecoder耗尽资源?

Microsoft Connect: System.ComponentModel.Win32Exception (0x80004005): 没有足够的存储空间来处理此命令

SO: 在后台线程中创建可冻结对象时存在资源泄漏


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接