Jon
Jon

Reputation: 1

Control.BeginInvoke not working with TextBox.AppendText, Cross Threading

I want to expose a method to update a text box with messages as a status log. I would like to use the AppendText method but I'm experiencing a strange multi threading issue when using it. I'm able to append new messages by concatenation just fine. The issue presents it's self as the text box not being shown, and then the Cross Thread access error shows up when closing the form. Here are examples of what works and what does not:

Working but not like AppendText unless extra steps are taken which is the last resort:

Public Sub AddMessage2(ByVal newMessage As String)
    If TextBoxStatus.InvokeRequired Then
        TextBoxStatus.BeginInvoke(Sub() TextBoxStatus.Text = TextBoxStatus.Text & newMessage & ControlChars.CrLf)
    Else
        TextBoxStatus.Text = TextBoxStatus.Text & newMessage & ControlChars.CrLf
    End If
End Sub

What I would like to use but does not work:

Public Sub AddMessage(ByVal newMessage As String)
    If TextBoxStatus.InvokeRequired Then
        TextBoxStatus.BeginInvoke(Sub() TextBoxStatus.AppendText(newMessage))
    Else
        TextBoxStatus.AppendText(newMessage)
    End If
End Sub

Additional info and updates: First of all I apologize for likely not supplying enough info up front.

At least part of the issue seems to be instantiating the form and calling AddMessage(newMessage) before calling Show() because the following code works:

Public Sub AddMessage(ByVal newMessage As String)
    If Me.Created Then
        If TextBoxStatus.InvokeRequired Then
            TextBoxStatus.BeginInvoke(Sub() TextBoxStatus.AppendText(newMessage))
        Else
            TextBoxStatus.AppendText(newMessage)
        End If
    End If
End Sub

I can always do something like the following, but I would like to what's going on :)

Private backLog As String = ""
Public Sub AddMessage(ByVal newMessage As String)
    If Me.Created Then
        If TextBoxStatus.InvokeRequired Then
            TextBoxStatus.BeginInvoke(Sub() TextBoxStatus.AppendText(backLog & newMessage))
        Else
            TextBoxStatus.AppendText(backLog & newMessage)
        End If
        backLog = ""
    Else
        backLog &= newMessage
    End If
End Sub

Also I don't consider this to be very elegant... especially when I add log size limits

Upvotes: 0

Views: 726

Answers (1)

jmcilhinney
jmcilhinney

Reputation: 54457

I would suggest this:

Public Sub AddMessage(ByVal newMessage As String)
    If TextBoxStatus.InvokeRequired Then
        TextBoxStatus.BeginInvoke(New Action(Of String)(AddressOf AddMessage), newMessage)
    Else
        TextBoxStatus.AppendText(newMessage)
    End If
End Sub

Upvotes: 0

Related Questions