2012-04-27 68 views
2

我正在嘗試編寫一個運行Perl腳本並讀取並使用標準輸出的VB .NET程序。我希望能夠在打印時分別處理每一行,並相應地更新我的程序顯示。下面是一些代碼,我已經「寫」(讀:「主要是複製了互聯網」):如何實時處理輔助過程的輸出?

Private WithEvents pscript As Process 

Private Sub myProgram_Load(sender As Object, e As System.EventArgs) Handles Me.Load 
    pscript = New Process() 
    pscript.StartInfo.CreateNoWindow = True 
    pscript.StartInfo.FileName = "C:\perl64\bin\perl.exe" 
    pscript.StartInfo.Arguments = "C:\test.pl" 
    pscript.StartInfo.UseShellExecute = False 
    pscript.StartInfo.RedirectStandardOutput = True 
    pscript.StartInfo.RedirectStandardInput = True 
    AddHandler pscript.OutputDataReceived, AddressOf pscript_output_process 
    pscript.Start() 
    pscript.BeginOutputReadLine() 
End Sub 

Private Sub pscript_output_process(sender As Object, e As DataReceivedEventArgs) 
    MessageBox.Show(e.Data) 
End Sub 

這適用於一個問題:程序等待,直到測試腳本運行完畢,然後觸發幾個OutputDataReceived事件一個接一個。這意味着,當我使用真正的腳本時,它可能會在幾個小時內不做任何事情,然後不得不一次處理5000個事件,儘管事實上是以相當規律的間隔印刷在那段時間。

有沒有什麼辦法可以讓它在處理每行文本時寫入文本,而不是一次處理所有文本?

+0

重定向標準輸出。 – dubvfan87 2012-04-27 22:51:48

+0

這可能既不存在也不存在,但幫助文檔反覆說明:「正在處理異步輸出的應用程序應該調用WaitForExit方法以確保輸出緩衝區已被刷新」 – 2012-04-27 23:50:07

+0

Jim:對WaitForExit的調用會導致應用程序完全凍結,直到腳本完成,否則它以同樣的方式工作。 – gorcq 2012-04-28 00:28:02

回答

0
While (pscript.HasExited = False) 
    Dim sLine As String = pscript.StandardOutput.ReadLine 
End While 
+0

出於某種原因,這隻會捕獲打印的第一行,並且仍然等待腳本完成。此外,它會導致我的程序在腳本運行時凍結,這就是爲什麼我喜歡基於事件的方法(如果它工作正常!)。 – gorcq 2012-04-28 00:35:24

1

我想通過從互聯網上覆制更多的東西來解決這個問題。問題似乎在Perl中,通常在每個打印語句後都不會刷新標準輸出。我不知道最後一句的含義是什麼,但無論如何,將local $| = 1;行添加到腳本的頂部(根據我讀的網站,它會自動刷新標準輸出),從而解決了這個問題。

+0

「沖洗標準輸出」有點草率。它應該說「刷新STDOUT的緩衝區」。爲了提高效率,默認使用快速RAM緩衝區;僅當緩衝區已滿或手動清空(「刷新」)時纔會將數據放入流(文件,終端,套接字)中。設置['| |'](http://p3rl.org/var#%24%7c)將關閉緩衝。 (我的解釋有點不準確,但要點是真實的;這裏沒有足夠的空間來提及更精細的細節。)閱讀[患有緩衝?](http://perl.plover.com/FAQs/Buffering.html)一個擴展的討論。 – daxim 2012-04-28 11:57:27

+0

謝謝你的文章。這使得現在更有意義。 – gorcq 2012-04-28 19:23:12