在VB.net中使用sleep时运行外部进程
我在用VB.net运行一个Python脚本时遇到了问题,因为这个程序让CPU的使用率飙升。简单来说,我是在VB.net程序里执行一个Python脚本,并且把标准输出重定向,这样Python脚本打印的内容就能被.net程序接收到。
Dim python_handler As New PythonHandler
python_handler.Execute("python.exe", "my_script.py")
' Wait for python_handler to get back data
While python_handler.pythonOutput = String.Empty
End While
Dim pythonOutput As String = python_handler.pythonOutput
这里的PythonHandler是一个类,它的Execute函数看起来是这样的:
Public Sub Execute(ByVal filePath As String, ByVal arguments As String)
If _process IsNot Nothing Then
Throw New Exception("Already watching process")
End If
_process = New Process()
_process.StartInfo.FileName = filePath
_process.StartInfo.Arguments = arguments
_process.StartInfo.UseShellExecute = False
_process.StartInfo.RedirectStandardInput = True
_process.StartInfo.RedirectStandardOutput = True
_process.Start()
_process.BeginOutputReadLine()
End Sub
Private Sub _process_OutputDataReceived(ByVal sender As Object, ByVal e As System.Diagnostics.DataReceivedEventArgs) Handles _process.OutputDataReceived
If _process.HasExited Then
_process.Dispose()
_process = Nothing
End If
RaiseEvent OutputRead(e.Data)
End Sub
Private Sub textProcessing_OutputRead(ByVal output As String) Handles Me.OutputRead
outputFetched = True
pythonOutput = output
End Sub
问题出在一个While循环上,因为它在等待Python脚本完成。这导致CPU使用率达到100%。我尝试在While循环里加上System.Threading.Thread.Sleep(200),但是这样一来,.net程序就无法接收到Python的输出,什么都没返回。可能是因为Process.BeginOutputReadLine()是异步的吧?
谢谢。
2 个回答
0
我看不出_process_OutputDataReceived
是怎么被分配给_process.OutputDataReceived
这个事件的。你应该在启动进程之前就把它分配好,然后调用_process.WaitForExit()
,而不是用你的循环。这样的话,它会自动阻塞,直到进程完成。至少我在C#的测试中是这样的。
_process = New Process()
_process.StartInfo.FileName = filePath
_process.StartInfo.Arguments = arguments
_process.StartInfo.UseShellExecute = False
_process.StartInfo.RedirectStandardInput = True
_process.StartInfo.RedirectStandardOutput = True
AddHandler _process.OutputDataReceived, AddressOf _process_OutputDataReceived
_process.Start()
_process.BeginOutputReadLine()
_process.WaitForExit()
0
为了更详细地解释Slippery Pete的回答……每当你使用异步方法时,几乎总是不应该用轮询循环来等待结果。下面这行代码会消耗很多处理器资源,这样做反而会失去使用异步方法带来的性能优势。
While python_handler.pythonOutput = String.Empty
End While
如果你发现自己在使用轮询循环,你应该问问自己是否有一种基于事件的方式来处理这个问题,或者在这种情况下,有没有更合适的方法来等待事件的发生。
_process.WaitForExit()