tags:

views:

67

answers:

4

Hi everyone.

Currently I am having a weird problem which I simply do not understand. I have a simple GUI, with one button & one richeditbox. I have an async socket running, I am receiving some data over the network which I want to print to the gui(richeditbox). The async socket is being started when the user hits the button. So when I receive the network data I call a function which prints the data, here how it looks like(in form1 class):

Public Sub AddText(ByVal text As String)

 Try

   Console.WriteLine(text)
   RichTextBox1.AppendText(text)
   RichTextBox1.AppendText(vbNewLine)

 Catch e As Exception
 Console.WriteLine(e.ToString())
 End Try

End Sub

Then I simply do Form1.AddText(..) from my network class or a module(does it matter?). The problem is that nothing appears in the richeditbox, even though the AddText function is being called, no exceptions, no errors, simply nothing. I've looked thru it with the debugger, and "text" contained the data it had to print, but simply nothing appears.. Anyone an idea? :/

+1  A: 

If the socket is running on another thread (which, of course, it is because it's asynchronous), you may have to use InvokeRequired in order to get the RichTextBox to display the text. I had a similar issue with a listener on an asynchronous serial port listener.

David Stratton
I've tried it already, but same result :/Private Delegate Sub dlgUpdate(ByVal text As String) Sub updateLog(ByVal text As String) If RichTextBox1.InvokeRequired = True Then Dim d As New dlgUpdate(AddressOf updateLog) RichTextBox1.Invoke(d, text) Else RichTextBox1.AppendText(text) End IfEnd SubNote: the updateLog function works if i call it from the gui thread, so i guess it is related to that, but i don't see why it still doesn't work after using InvokeRequired.
uh.. that looks ugly, can't even see the code in the comment, I took the code from: http://www.vbdotnetforums.com/asp-net-data-access/19740-how-use-invokerequired.html
This may be a dumb suggestion, but if the UI thread is locked, you could always try throwing in an Application.DoEvents() after appending the text.
David Stratton
Thanks, but it crashes as soon as the other thread uses the AddText function from below.
+1  A: 

I'm pretty sure David is right. Here's an example.

Delegate Sub AddTextDelegate(ByVal text as String)

Public Sub AddText(ByVal text as String)
    If Me.InvokeRequired Then
        Me.Invoke(new AddTextDelegate(AddressOf Me.AddText), new object() { text })
    Else
        Try
            Console.WriteLine(text)
            RichTextBox1.AppendText(text)
            RichTextBox1.AppendText(vbNewLine)
        Catch e as Exception
            Console.WriteLine(e.ToString())
        End Try
    End If
End Sub

The deal is that controls have to be updated on the thread they were created on. It sounds like the AddText() routine is being called in the context of your async socket's thread. The AddText() routine will behave like a recursive function. The first time it's called, the InvokeRequired property will be true. This will cause it to be called again via the Invoke() call, which takes care of marshaling the data to the correct thread. The second time it's called, InvokeRequired will be false, and the control will be updated.

Matt Davis
Hm thanks, still doesn't work though. I've checked with the debugger and everytime the function got called InvokeRequired was "false". And yea, it's related to it, because when debugging I see that addText function is not being called from the "MainThread". Thanks for your help!
I meant that the AddText function only worked when it's being called from the MainThread, e.g on Form1_Load.
A: 

No one has any other idea? :/ Thanks.

How quickly is the AddText() method being called? If it's real early during initialization, there's a chance the handle hasn't been created yet, in which case, InvokeRequired will always return false. See this link: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.invokerequired.aspx
Matt Davis
A: 

Fixed. I couldn't use Form1 to call the functions, because it's a type, its like a new var there with its own memory, since its a diff thread. So when I checked InvokeRequired, it said false because that Form1 belongs to that Thread, and thus no text was being displayed because I didn't even see the form. So just made a global var such as Public myForm As Form1 and assigned myForm to Form1 in Form1_Load.