Buho1
Member
Hi. I've been searching around the web and here for several days and haven't found a solution to my problem. I'm a veteran ASP.NET developer but I'm new to WinForms and multithreading. I'm using VS 2010 and VB.NET 4.0.
I have a console application that takes minutes to hours to run. It spits out to the standard output what it's doing. My client now wants a GUI for this app (command line parameters and XML scare them) and the quickest solution is to write a WinForm that launches the console app.
I've successfully written this application. Here's the core code I have at this point:
Now, I've learned that WaitForExit() is a synchronous operation, so if I want to use a BackgroundWorker and use this snippet, that's a bad idea.
I've experimented with BackgroundWorker but results haven't been much better. The main form and the output window are responsive, but the output window shows no output until the process completes, where it shows everything.
Here's what I've got with BackgroundProcess:
Any ideas on how to display a fluid StandardOutput?
I have a console application that takes minutes to hours to run. It spits out to the standard output what it's doing. My client now wants a GUI for this app (command line parameters and XML scare them) and the quickest solution is to write a WinForm that launches the console app.
I've successfully written this application. Here's the core code I have at this point:
Private bcProcess As New Process Private Sub btnProcess_Click() Handles btnProcess.Click runBCMaker() End Sub Private Sub runBCMaker() Try openOutputWindow() bcProcess.StartInfo.FileName = defaultBCMakerFilename bcProcess.StartInfo.Arguments = makeCmdArg() bcProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden 'Output will be shown in a WinForm bcProcess.StartInfo.CreateNoWindow = True 'Line above didn't work, try this. bcProcess.StartInfo.UseShellExecute = False bcProcess.StartInfo.RedirectStandardOutput = True bcProcess.Start() outputWindow.Output = bcProcess.StandardOutput.ReadToEnd() bcProcess.WaitForExit() bcProcess.Close() lblProcess.Text = "Process finished." Catch ex As Exception lblProcess.Text = "BCMaker.exe crashed!" Finally bcProcess.Dispose() End Try End SubThis will open another WinForm that I've made, basically a big Textbox with a public property Output that I can assign the StandardOutput.ReadToEnd() to. The WinForm will freeze for the minutes that my program (BCMaker.exe) is running and then come back, with the output in the Output window. Fine. I met the requirements of my project. Except this freeze will likely aggravate my client, especially when they can't see any progress.
Now, I've learned that WaitForExit() is a synchronous operation, so if I want to use a BackgroundWorker and use this snippet, that's a bad idea.
I've experimented with BackgroundWorker but results haven't been much better. The main form and the output window are responsive, but the output window shows no output until the process completes, where it shows everything.
Here's what I've got with BackgroundProcess:
Private bcProcess As New Process Private WithEvents BackgroundWorker1 As New BackgroundWorker Private Sub btnProcess_Click() Handles btnProcess.Click openOutputWindow() BackgroundWorker1.RunWorkerAsync() End Sub Private Sub runBCMaker() Try bcProcess.StartInfo.FileName = defaultBCMakerFilename bcProcess.StartInfo.Arguments = makeCmdArg() bcProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden 'Output will be shown in a WinForm bcProcess.StartInfo.CreateNoWindow = True 'Line above didn't work, try this. bcProcess.StartInfo.UseShellExecute = False bcProcess.StartInfo.RedirectStandardOutput = True bcProcess.Start() outputWindow.Output = bcProcess.StandardOutput.ReadToEnd() bcProcess.Close() Catch ex As Exception lblProcess.Text = "BCMaker.exe crashed!" Finally bcProcess.Dispose() End Try End Sub Private Sub runBCMaker_Completed(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted If e.Cancelled Then lblProcess.Text = "Canceled!" ElseIf e.Error IsNot Nothing Then lblProcess.Text = "Error: " + e.Error.Message Else lblProcess.Text = "Done!" End If End SubBackgroundWorker.ProgressChanged event is no good, since there's nothing discernible my console app is reporting; I'm redirecting the StandardOutput stream. Maybe if ProgressChangedEventArgs could contain a data payload I could send the standard output of the console through periodically (like every 100ms), but I don't see a way to send any data payload this way.
Any ideas on how to display a fluid StandardOutput?