大多数时候,作为.Net开发人员工作,我们可以自由地在我们的高级抽象世界中捣乱,但有时候现实会让你在私密部分踢你,并告诉你找一个真的理解。
我刚刚有过这样的经历之一。我认为只需将角落数据列为项目列表就可以了解我们的内容:
System.ComponentModel.Win32Exception (0x80004005): Not enough quota is available to process this command at MS.Win32.UnsafeNativeMethods.PostMessage(HandleRef hwnd, WindowMessage msg, IntPtr wparam, IntPtr lparam) at System.Windows.Interop.HwndTarget.UpdateWindowSettings(Boolean enableRenderTarget, Nullable`1 channelSet) at System.Windows.Interop.HwndTarget.UpdateWindowPos(IntPtr lParam) at System.Windows.Interop.HwndTarget.HandleMessage(WindowMessage msg, IntPtr wparam, IntPtr lparam) at System.Windows.Interop.HwndSource.HwndTargetFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o) at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs) at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
编辑#1 经过一番检查,这里有更多细节:
启动是一个两步过程,Launcher启动一个中间件 使用Process.WaitForExit()
从中间窗口,可以以相同的方式启动更多进程(Process.WaitForExit)。
只有中间窗口打开且没有用户交互,启动程序进程的句柄数量会随着时间的推移而增加。我们在这里看到的最大增幅是400 - > 6000把手。
编辑中添加的事实确实让我想知道框架中是否存在句柄泄漏。我正在尝试隔离问题并检查是否可以从头开始重现。与此同时,很高兴接受任何提示,想法,支持甚至巧克力!
编辑#2 :为了使流程对PostMessage()
做出响应,我们删除了Thread.WaitForExit
。相反,我们为Process的Exited事件添加了一个Handler,并将Launcher发送到如下循环:
while (foo == true)
{
System.Threading.Thread.Sleep(1000);
}
退出处理程序将foo
设置为false,不执行任何其他操作。
Handles的数量仍在增加(半小时内400到800)。
编辑#3 终于有了一些有趣的东西。
while (foo == true)
{
System.Threading.Thread.Sleep(1000);
GC.Collect();
}
这使它保持原样,几乎没有把手,都很漂亮。现在这让我想知道这里有什么问题......我会再次与负责人讨论,以检查发射器的其他功能。到目前为止,我听说它使用XmlDocument.Load()读取了一些配置值,这不是IDisposable
- 这使得在这里产生任何泄漏很难......
答案 0 :(得分:5)
错误告诉您窗口的消息队列在向其发布消息时达到了其最大容量。这意味着拥有该窗口的线程没有足够快地处理消息,如果有的话。
答案 1 :(得分:1)
我知道这个问题已有六年历史了,但是我们遇到了同样的问题,我以此为灵感。我不喜欢的是休眠线程和循环的想法。
相反,我创建了一个WPF窗口。使其透明并高一个像素,并为其添加了Process类型的公共属性。
然后,我没有调用.WaitForExit,而是写了一个Shared Sub(对不起,我使用的是VB.NET术语),可以完成以下操作
Public Shared Sub DoWaitForProcessToExit(ByVal poProc As Process, ByVal oOwner As Window)
Dim oWFE As WaitForProcessToExit
poProc.EnableRaisingEvents = True
oWFE = New WaitForProcessToExit
oWFE.oProc = poProc
If Not oOwner Is Nothing Then
oWFE.Owner = oOwner
End If
oWFE.ShowDialog()
oWFE = Nothing
End Sub
只需,以防发生某些疯狂事件,并且在激活此对话框时该过程已经退出:
Private Sub WaitForProcessToExit_Activated(sender As Object, e As EventArgs) Handles Me.Activated
Try
If oProc.HasExited Then
Try
RemoveHandler oProc.Exited, AddressOf oProc_Exited
Catch ex As Exception
End Try
'whatever happened .... it seems to have gone too quick for this to invoke the _Exited event
Me.Close()
End If
Catch
Try
Try
RemoveHandler oProc.Exited, AddressOf oProc_Exited
Catch ex As Exception
End Try
Me.Close()
Catch
End Try
End Try
End Sub
现在,仅在加载对话框时才需要这样做:
Private Sub WaitForProcessToExit_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
AddHandler oProc.Exited, AddressOf oProc_Exited
End Sub
然后仅响应Exited事件。没有睡眠,没有循环。
Private Sub oProc_Exited(sender As Object, e As EventArgs)
'This event is raised by the exiting process, which is in a different thread, so, invoke my own
'close method from my own Dispatcher
Windows.Application.Current.Dispatcher.Invoke(Sub() CloseMe(), Windows.Threading.DispatcherPriority.Render)
End Sub
Private Sub CloseMe()
Me.Close()
End Sub