Home > database >  How can i add a msgbox at the end of the stream
How can i add a msgbox at the end of the stream

Time:01-10

I wrote a file streamer that reads live data being written in a txt file and displays that data in a richtextbox.

The problem is I want it to scroll down automatically as new text is added, and also at the end of the stream to show a msgbox that the stream ended.

This is the code:

Private Sub btnRadOnly_Click(sender As Object, e As EventArgs) Handles btnRadOnly.Click
    RichTextBox1.Invoke(Sub()
                            RichTextBox1.Text = ""
                        End Sub)
    t = New Thread(Sub()
                       bStop = False
                       While (Not bStop)
                           Thread.Sleep(500)
                           RichTextBox1.Invoke(Sub()
                                                   Using fs = New FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
                                                       Using sr = New StreamReader(fs, Encoding.Default)
                                                           RichTextBox1.Text = sr.ReadToEnd()
                                                       End Using
                                                   End Using
        

             End Sub)
                       End While
                   End Sub)
    t.Start()
End Sub

How can I do this?

CodePudding user response:

I think I gave you enough to answer your questions in comments, but here is an alternate way to do it, using Async / Await

Private Async Sub btnRadOnly_Click(sender As Object, e As EventArgs) Handles btnRadOnly.Click
    Await fooAsync()
End Sub

Private Function fooAsync() As Task
    Return Task.Run(
    Sub()
        RichTextBox1.Invoke(Sub() RichTextBox1.Text = "")
        bStop = False
        While (Not bStop)
            Thread.Sleep(500)
            Dim s As String
            Using fs = New FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
                Using sr = New StreamReader(fs, Encoding.Default)
                    s = sr.ReadToEnd()
                End Using
            End Using
            RichTextBox1.Invoke(
                Sub()
                    RichTextBox1.Text = s
                    RichTextBox1.Select(RichTextBox1.Text.Length, 0)
                End Sub)
        End While
        Me.Invoke(Sub() MessageBox.Show("Done"))
    End Sub)
End Function

CodePudding user response:

It might be tempting to add code like this after t.Start()

t.Join() 'Wait for thread to finish
MessageBox.Show("Finished")

But that would be a mistake. It would eliminate much of the benefit of using a separate thread for this, and cause the application to become unresponsive until it finishes. I think you understand that or you wouldn't be using threads in the first place, but this is useful to mention.

Once upon a time I would have solved this instead with a timer component to poll the t.ThreadState or t.IsAlive properties, and show the MessageBox when those change. This is still a reasonable approach; the downside is it's not so good at re-entry. You need to make sure someone doesn't click the button again and start the process a second time before the first finishes. It also spreads this feature across code in multiple locations. The good news is it gives you a nice place to check whether to scroll the richtextbox.

Another option is using a BackgroundWorker control. It lets you do this in a way that will avoid needing to call Invoke() or manually create any threads. You can pass the text back to the RichTextbox on the main form via the ProgressChanged or WorkCompleted events.

Modern code recommends an Aysnc/Await approach. This has better handling of the re-entry issue partially built in, such that you should be able to just put the MessageBox at the end of the method, with no separate timer needed. There's another answer already covering how to use it.

In either case, I suggest switching from sr.ReadToEnd() to using sr.ReadLine() in a loop. This will allow you to update (and scroll) the RichTextBox in a more granular way, as data arrives on the stream. Otherwise, there's no good way to update the RichText on the screen until the entire process is finished.

  • Related