Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Process delegate updates textbox.text but the textbox does not repaint until process finished

Status
Not open for further replies.

Yorkshireman2

Programmer
Jan 21, 2005
154
CA
There are many similar problems on the internet but none have solved this exact problem.
I use a process and delegate to call a c program and redirect output to a textbox.
I want the textbox to update line by line, in real time. BUT it seems to wait until a large chunk of text is in the textbox.text property before repainting it.


Code:
     Private Sub cmdReadFields_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdReadFields.Click
        
        txtOutput.AppendText(vbCrLf & "Reading Fields from " & gstrSimulatorType & vbCrLf)
        mProcess = New Process

        AddHandler mProcess.OutputDataReceived, AddressOf process_OutputDataReceived
        AddHandler mProcess.ErrorDataReceived, AddressOf process_OutputDataReceived
        ' handlers should send both output and errors to same handling sub

        ' now can call the c program in a process (separate thread) and redirect the output to the textbox
        Dim startInfo As New ProcessStartInfo
        startInfo.FileName = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory(), "ReadFields\ReadFieldsInfo.exe")
        startInfo.WorkingDirectory = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory(), "ReadFields")
        startInfo.UseShellExecute = False
        startInfo.CreateNoWindow = True
        'startInfo.RedirectStandardInput = True    'doesn't seem to help, so commented out
        startInfo.RedirectStandardOutput = True
        startInfo.RedirectStandardError = True
        startInfo.ErrorDialog = True
        mProcess.StartInfo = startInfo
        mProcess.EnableRaisingEvents = True

        Try
            mProcess.Start()
            mProcess.BeginOutputReadLine()
            mProcess.BeginErrorReadLine()

        Catch ex As Exception
            MsgBox("error" & ex.Message)

        Finally
            mProcess.Close()  ' tried commenting this out - no change
            mProcess.Dispose()  ' tried commenting this out - no change
        End Try

     End Sub
    
    ' fires from handler, when output data rcvd from process 
    Public Sub process_OutputDataReceived(ByVal sender As Object, ByVal e As DataReceivedEventArgs)
        ' called as the handler for data output being detected in the redirect
        UpdateTextBox(e.Data)
    End Sub

    Delegate Sub UpdateTxtBoxDelegate(ByVal Text As String)

    Public Sub UpdateTextBox(ByVal Tex As String)
        If txtOutput.InvokeRequired Then
            Dim myDelegate As New UpdateTxtBoxDelegate(AddressOf UpdateTextBox)
            Dim args As Object() = {Tex}
            Me.txtOutput.Invoke(myDelegate, args)
        Else
            txtOutput.AppendText(Tex & Environment.NewLine)
            ' application.doEvents   ' tried this but only refreshes GUI when stepping through code with F11
        End If
    End Sub

Note 1: I found none of the delegate calls run until the main sub cmdReadFields_Click() finishes and exits;
THEN all the calls to the delegate are executed and the text box prints out all the text at the end.
Interesting- I thought a separate thread would be running these delegate events while the GUI command button event is still running.

Note 2: I tried a breakpoint in the UpdateTextBox() sub and I watched the value of txtOutput.text.
The text property was actually updating at each call but the GUI textbox did NOT update/refresh until it was 'nearly all done'.

When the c program runs in a console it prints to screen a line-by-line report of what the code is doing as it creates a copy of a dll,
creates an object in memory and reads data fields from that object then destroys the object and dll copy.
( The c program prints a line feed after each line and flushes the buffer )

HOWEVER, WHEN the c program runs in the vb.net thread (process), the textbox shows nothing while the console program is gradually printing out the
creation messages, reading data values etc. then the textbox suddenly updates to show the entire block of text lines; Then it again pauses while the
c program is destroying the objects and printing out strings about this; THEN the textbox suddenly prints those lines out.

Note 3: I tried application.doEvents, as many internet posts suggest, but that does not refresh the textbox in real time either.
In fact... when I put a breakpoint in the UpdateTextBox() sub and let it run one call at a time, the GUI actually DID update the textbox at each line BUT when I
run the code without the breakpoint, the textbox does NOT update for each line.
I can only assume the successful update when stepping through the code is because the IDE is passing focus between the GUI and code as I step through,
whereas in continuous run mode the textbox never receives a paint message.(?)

Note 4: I also tried using an exit event for the process at one time and I had tried commenting out the mProcess.close and mProcess.dispose statements
inside the main sub in case I was somehow destroying the process before my exit event was called but that did not help anything.


***** SO.. Has anyone already solved this?
How do I get the textbox to actually repaint at each update of the .text property so my lines are printed out one at a time, in real time, as the c program is doing behind the scenes???
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top