.net 诊断;超过配额;Win32异常
大多数时候,作为一名.Net开发人员,我们可以自由地在高层次的抽象世界中游手好闲,但有时现实会在你的隐私部分踢你一脚,告诉你找到一个真正理解的人 我刚刚有过这样的经历。我认为将角落数据列为项目列表就足够了,这样您就可以了解我们这里的内容:.net 诊断;超过配额;Win32异常,.net,wpf,performance,winapi,win32exception,.net,Wpf,Performance,Winapi,Win32exception,大多数时候,作为一名.Net开发人员,我们可以自由地在高层次的抽象世界中游手好闲,但有时现实会在你的隐私部分踢你一脚,告诉你找到一个真正理解的人 我刚刚有过这样的经历。我认为将角落数据列为项目列表就足够了,这样您就可以了解我们这里的内容: Win2008服务器 64位环境 多个客户端同时使用的WPF应用程序 应用程序是一个启动器,它使用Process.Start()打开其他应用程序 偶尔我们会遇到下面列出的例外情况 编辑#1 经过一些检查,这里有更多的细节: 发射是一个两步过程,发射器发射
- Win2008服务器
- 64位环境
- 多个客户端同时使用的WPF应用程序
- 应用程序是一个启动器,它使用Process.Start()打开其他应用程序
- 偶尔我们会遇到下面列出的例外情况
- 发射是一个两步过程,发射器发射一个中间过程 使用Process.WaitForExit()的窗口
- 在中间窗口中,可以以相同的方式启动其他进程(Process.WaitForExit)
- 只有中间窗口打开,没有用户交互,启动程序进程的句柄数量会随着时间的推移而增加。我们在这里看到的最大增加是400-->6000个句柄
PostMessage()
,我们删除了线程。WaitForExit
。相反,我们为流程的Exited事件添加了一个处理程序,并将启动器发送到一个循环中,如下所示:
while (foo == true)
{
System.Threading.Thread.Sleep(1000);
}
退出的处理程序将foo
设置为false,并且不执行其他操作。
尽管如此,手柄的数量还是在增加(半小时内从400个增加到800个)
编辑#3
终于有有趣的事情发生了
while (foo == true)
{
System.Threading.Thread.Sleep(1000);
GC.Collect();
}
这使它保持了它应该是的样子,几个把手,所有漂亮的。现在这让我想知道这里出了什么问题……我将再次与负责的开发人员交谈,以检查启动器的其他功能。到目前为止,我听说它使用读取一些配置值,这不是一个
IDisposable
-这使得在这里很难产生任何泄漏…错误告诉您,在向窗口发布消息时,窗口的消息队列已达到其最大容量。这意味着拥有该窗口的线程处理消息的速度不够快(如果有的话)。我知道这个问题已经提出六年了,但我们刚刚遇到了同样的问题,我用它来启发自己。但我不喜欢的是睡线和圈的想法
相反,我创建了一个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
嗯。这可能会返回到Thread.WaitForExit(),这会使线程在子线程退出之前没有响应……谢谢,我将尝试使用基于事件的方式处理进程退出,并在这里发回反馈。请注意,这实际上只是替换了.WaitForExit调用。调用代码应该已经负责关闭和处理进程对象,并在必要时进行垃圾收集。
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