在诊断“超出配额” Win32Exception(Diagnosis on “Quota Excee

2019-09-16 10:41发布

大部分的工作作为一个.NET开发人员的时间给了我们自由地浪费时间在我们的高级别的抽象世界,但有时现实踢你的私处,并告诉你找到一个男人谁真正理解。

我刚刚的这些经验之一。 我认为这将足以列出角落的数据作为一个项目列表让你了解我们在这里:

  • 的Win2008服务器
  • 64位环境
  • 同时被多个客户使用WPF应用程序
  • 应用程序是一个发射器,打开使用的Process.Start其他应用程序()
  • 有时,我们得到以下列出的除外
 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一些检查后,这里的更多详细信息:

  • 发射是一个两步骤的过程中,启动器启动使用Process.WaitForExit中间窗口()

  • 从中间窗口,进一步处理可以以相同的方式(Process.WaitForExit)启动。

  • 由于只有中间窗口打开,没有用户交互,启动过程的句柄的数量随时间而增加。 我们在这里看到的最大增加400 - > 6000手柄。

在编辑添加的事实,真的让我怀疑是否有可能是在框架中的句柄泄露的地方。 我试图找出问题,并检查是否我可以从头开始重现。 在此期间,任何一种暗示,想法,支持甚至巧克力是欣然接受!

编辑#2:在试图使这一进程响应PostMessage()我们去掉了Thread.WaitForExit 。 相反,我们增加了对过程的已退出事件的处理程序和发送的启动到像下面这样的循环:

       while (foo == true)
        {
            System.Threading.Thread.Sleep(1000);
        }

已退出处理程序设置foo为false,并没有别的。 仍然,柄的数量的增加(400到800在半小时内)。

编辑#3来了一些有趣的事情,在最后。

       while (foo == true)
        {
            System.Threading.Thread.Sleep(1000);
            GC.Collect();
        }

这使得它,它应该是,几个把手,所有漂亮的方式。 现在,让我不知道什么是错在这里...我会再跟负责开发人员回来检查发射做什么。 到目前为止,我听说它读取使用一些配置值XMLDocument.load方法() ,这是不是一个IDisposable -使得一种很难在这里产生任何泄漏...

Answer 1:

该错误是告诉你,一个窗口的消息队列发布消息,就当达到其最大容量。 这意味着,拥有该窗口没有处理邮件速度不够快,如果在所有的线程。



Answer 2:

我知道这个问题是六岁,但我们刚刚有同样的问题发生在我们身上,我用这个灵感。 我不喜欢,虽然是睡着的线程和循环的理念。

相反,我创建了一个WPF窗口。 使其透明和一个像素高和宽,和添加型过程的公共属性给它。

然后,而不是调用.WaitForExit,我写了一个共享子(抱歉,我使用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

然后只回应已退出事件。 不睡,没有循环。

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


文章来源: Diagnosis on “Quota Exceeded” Win32Exception