環境:VB.NET2005, VISTA
(処理が長めの)バッチファイルを実行し、出力結果を取得したいのですが、
Me.Invokeの箇所で処理が停止してしまいます。
Invokeの使い方が間違っているのでしょうか?
※テスト用としてouttree.batは「tree /f>tree.txt」が複数行書いてあります
Private Sub Button1_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
subExecute("C:\temp\outtree.bat", "", "C:\temp\")
End Sub
Private Sub subWriteLog(ByVal strMsg As String)
Debug.Print(strMsg) '実際にはファイルに出力する処理
End Sub
Private Sub subExecute(ByVal strCmd As String, ByVal strArg As String, ByVal strWorkPath As String)
Dim hProcess As New System.Diagnostics.Process
hProcess.StartInfo.Arguments = strArg
hProcess.StartInfo.UseShellExecute = False
hProcess.StartInfo.FileName = strCmd
hProcess.StartInfo.WorkingDirectory = strWorkPath
hProcess.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden '非表示
hProcess.StartInfo.CreateNoWindow = True
hProcess.StartInfo.RedirectStandardOutput = True '標準出力をリダイレクト
hProcess.StartInfo.RedirectStandardError = True
AddHandler hProcess.OutputDataReceived, New DataReceivedEventHandler(AddressOf processOutDataReceived)
AddHandler hProcess.ErrorDataReceived, New DataReceivedEventHandler(AddressOf processErrDataReceived)
Try
hProcess.Start()
hProcess.BeginOutputReadLine()
hProcess.BeginErrorReadLine()
hProcess.WaitForExit()
Catch ex As Exception
MessageBox.Show(ex.Message)
Finally
'解放
hProcess.Close()
hProcess.Dispose()
End Try
End Sub
'スレッドから関数を呼び出すための宣言
Private Delegate Sub subWriteLogDelegate(ByVal strMsg As String)
'標準出力取得(スレッド)
Private Sub processOutDataReceived(ByVal sender As System.Object, ByVal e As DataReceivedEventArgs)
If String.IsNullOrEmpty(e.Data) = False Then
Dim Proc As New subWriteLogDelegate(AddressOf subWriteLog)
Me.Invoke(Proc, e.Data)
End If
End Sub
'エラー出力取得(スレッド)
Private Sub processErrDataReceived(ByVal sender As System.Object, ByVal e As DataReceivedEventArgs)
If String.IsNullOrEmpty(e.Data) = False Then
Dim Proc As New subWriteLogDelegate(AddressOf subWriteLog)
Me.Invoke(Proc, e.Data)
End If
End Sub
subExecute 自体はメインスレッドで動いてますよね。
で、その中で Process.WaitForExit してます。
これでメインスレッドが止まります。
その後、サブスレッドが Invoke します。メインスレッドがデリゲートで渡した処理を完了するまで制御が返りません。
ところがそのメインスレッドは停止中です。
永遠に制御は返りません。
WaitForExit はやめて、Exited イベント辺りを使うのが自然でしょうかね。
// Exited はヘルプの解説を読まないとちょっとはまります。
Hongliangさん、
解りやすい回答ありがとうございます。
確かにデッドロックになってしまいますね。
> WaitForExit はやめて、Exited イベント辺りを使うのが自然でしょうかね。
> // Exited はヘルプの解説を読まないとちょっとはまります。
こちらの方を試してみます。
ツイート | ![]() |