[VB.NET 2008] How to write in a textbox from another thread
-
Hi everybody, I have a simple project with a form and a class in another file to manage the COM port (from the article "Smart Device Print Engine for Compact Framework" by Orkun GEDiK). I open the COM port and I start its thread for receiving data. I want to write the received data in a textbox in the form. To do this, every byte I receive, I assign the value of this byte to a byte variable of the form called
byt
and I call from inside the loop of the thread a function in the form that stores all the bytes in a stringdati
(in hexadecimal format):Public Sub ScriviTesto2()
Dim str As StringIf InvokeRequired Then Invoke(New Action(AddressOf ScriviTesto2)) Return End If Try str = Hex(byt) dati &= str & " " Catch ex As Exception MessageBox.Show(ex.ToString) End Try
End Sub
This seems to work because if I run the code step by step I see that the string
dati
grows byte by byte and contains the correct values. When there are no more bytes to receive, always from inside the loop of the thread, I call another function of the form that should write my string in a text box:Public Sub ScriviTesto3()
If InvokeRequired Then Invoke(New Action(AddressOf ScriviTesto3)) Return End If TB1.Text &= dati & vbCrLf
End Sub
...this function write nothing in the text box... why? The string
data
contains the right values, is not empty. I tried another way: I don't call the last funcion (ScriviTesto3()
) but, when there are no more bytes to receive, I click a button of the form that do the same:Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
TB1.Text &= dati & vbCrLf
End SubIn this case, when I click the button the string
dati
is empty... I don't know why. I add the declaration of the involved variables:Public Class Form1
Public byt As Byte
Protected dati As String
...Can anyone help me? Thanks in advance.
-
Hi everybody, I have a simple project with a form and a class in another file to manage the COM port (from the article "Smart Device Print Engine for Compact Framework" by Orkun GEDiK). I open the COM port and I start its thread for receiving data. I want to write the received data in a textbox in the form. To do this, every byte I receive, I assign the value of this byte to a byte variable of the form called
byt
and I call from inside the loop of the thread a function in the form that stores all the bytes in a stringdati
(in hexadecimal format):Public Sub ScriviTesto2()
Dim str As StringIf InvokeRequired Then Invoke(New Action(AddressOf ScriviTesto2)) Return End If Try str = Hex(byt) dati &= str & " " Catch ex As Exception MessageBox.Show(ex.ToString) End Try
End Sub
This seems to work because if I run the code step by step I see that the string
dati
grows byte by byte and contains the correct values. When there are no more bytes to receive, always from inside the loop of the thread, I call another function of the form that should write my string in a text box:Public Sub ScriviTesto3()
If InvokeRequired Then Invoke(New Action(AddressOf ScriviTesto3)) Return End If TB1.Text &= dati & vbCrLf
End Sub
...this function write nothing in the text box... why? The string
data
contains the right values, is not empty. I tried another way: I don't call the last funcion (ScriviTesto3()
) but, when there are no more bytes to receive, I click a button of the form that do the same:Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
TB1.Text &= dati & vbCrLf
End SubIn this case, when I click the button the string
dati
is empty... I don't know why. I add the declaration of the involved variables:Public Class Form1
Public byt As Byte
Protected dati As String
...Can anyone help me? Thanks in advance.
steve_9496613 wrote:
I call another function of the form that should write my string in a text box:
Pass the data to display there as a parameter.
steve_9496613 wrote:
In this case, when I click the button the string
dati
is empty... I don't know why.Access to the form's field isn't thread-safe. You could lock it in a property, but that slow down things nicely. Hence, I'd suggest to create a list of bytes on your receiver-thread, and to pass this as a paramater to the form, say, once a second.
Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]
-
steve_9496613 wrote:
I call another function of the form that should write my string in a text box:
Pass the data to display there as a parameter.
steve_9496613 wrote:
In this case, when I click the button the string
dati
is empty... I don't know why.Access to the form's field isn't thread-safe. You could lock it in a property, but that slow down things nicely. Hence, I'd suggest to create a list of bytes on your receiver-thread, and to pass this as a paramater to the form, say, once a second.
Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]
Thanks Eddy. I have modified the first function as you suggested to do for the second one:
Public Sub ScriviTesto2(ByVal dato As Byte)
Dim str As StringIf InvokeRequired Then Invoke(New Action(Of Byte)(AddressOf ScriviTesto2), dato) 'Invoke(New Action(AddressOf ScriviTesto2)) Return End If Try 'str = Hex(byt) 'dati &= str & " " str = Hex(dato) dati &= str & " " TB1.Text &= Hex(dato) & " " 'TB1.Text = dati Catch ex As Exception MessageBox.Show(ex.ToString) End Try
End Sub
In the receiver thread I call this function every byte I receive, passing to it the byte just received. As before the string
dati
grows byte by byte so I can say that I correctly pass the parameterdato
to this function but nothing is written in the text boxTB1
. Writing byte by byte in a textbox is not the fastest way but I just wanted to see if passing data as parameter to the function could be the solution. Perhaps the text box is not the right objet to use or, more likely, I'm missing something important. I did another try: as you suggested I created a byte array in the receiver thread, I fill it with the bytes received and at the end of data reception I call another function in form1 passing to it the byte array:Public Sub ScriviTesto4(ByVal datiIn As Byte())
Dim i As Int32If InvokeRequired Then Invoke(New Action(Of Byte())(AddressOf ScriviTesto4)) Return End If For i = 0 To (datiIn.Count - 1) TB1.Text &= Hex(datiIn(i)) & " " Next TB1.Text &= vbCrLf
End Sub
Running step by step in debug I see that the array
datiIn
contains the right bytes and also theTB1.Text
contains the right values but I see nothing in the text box in the form! What I'm doing wrong? -
Thanks Eddy. I have modified the first function as you suggested to do for the second one:
Public Sub ScriviTesto2(ByVal dato As Byte)
Dim str As StringIf InvokeRequired Then Invoke(New Action(Of Byte)(AddressOf ScriviTesto2), dato) 'Invoke(New Action(AddressOf ScriviTesto2)) Return End If Try 'str = Hex(byt) 'dati &= str & " " str = Hex(dato) dati &= str & " " TB1.Text &= Hex(dato) & " " 'TB1.Text = dati Catch ex As Exception MessageBox.Show(ex.ToString) End Try
End Sub
In the receiver thread I call this function every byte I receive, passing to it the byte just received. As before the string
dati
grows byte by byte so I can say that I correctly pass the parameterdato
to this function but nothing is written in the text boxTB1
. Writing byte by byte in a textbox is not the fastest way but I just wanted to see if passing data as parameter to the function could be the solution. Perhaps the text box is not the right objet to use or, more likely, I'm missing something important. I did another try: as you suggested I created a byte array in the receiver thread, I fill it with the bytes received and at the end of data reception I call another function in form1 passing to it the byte array:Public Sub ScriviTesto4(ByVal datiIn As Byte())
Dim i As Int32If InvokeRequired Then Invoke(New Action(Of Byte())(AddressOf ScriviTesto4)) Return End If For i = 0 To (datiIn.Count - 1) TB1.Text &= Hex(datiIn(i)) & " " Next TB1.Text &= vbCrLf
End Sub
Running step by step in debug I see that the array
datiIn
contains the right bytes and also theTB1.Text
contains the right values but I see nothing in the text box in the form! What I'm doing wrong?steve_9496613 wrote:
Perhaps the text box is not the right objet to use or, more likely, I'm missing something important.
It's not optimal, but it should display some text. That's what it's there for.
steve_9496613 wrote:
Running step by step in debug I see that the array
datiIn
contains the right bytes and also theTB1.Text
contains the right values but I see nothing in the text box in the form!Did you create the textbox on the mainthread?
For i = 0 To (datiIn.Count - 1)
string x = Hex(datiIn(i)) & " "
TB1.Text = TB1.Text + x
NextCan you write the string x to the debugger?
Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]
-
steve_9496613 wrote:
Perhaps the text box is not the right objet to use or, more likely, I'm missing something important.
It's not optimal, but it should display some text. That's what it's there for.
steve_9496613 wrote:
Running step by step in debug I see that the array
datiIn
contains the right bytes and also theTB1.Text
contains the right values but I see nothing in the text box in the form!Did you create the textbox on the mainthread?
For i = 0 To (datiIn.Count - 1)
string x = Hex(datiIn(i)) & " "
TB1.Text = TB1.Text + x
NextCan you write the string x to the debugger?
Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]
Eddy Vluggen wrote:
Did you create the textbox on the mainthread?
I added the textbox to the form1 in the designer, it should be in the main thread. In form1 I declared an instance of the class to manage the COM:
Dim NewCom As CommDev
In the Load event of the form I create the new object:
NewCom = New CommDev()
In the
New
function of the class some parameters are set, like baud rate, parity, etc. When I open the COM port, I call anInit
function that opens the COM port, sets buffer sizes, sets the device control block, sets timeouts, creates and starts the receiver thread.Eddy Vluggen wrote:
Can you write the string x to the debugger?
I used your code instead of mine and I can see the value of the string
x
, I mean that I can "add an expression control" (I don't know if this is the right translation of the italian "Aggiungi espressione di controllo" that appear in the right click menu over a variable during debug) to the stringx
and see its right value in the bottom windows of Visual Studio. Nothing appears in the textbox... I made also another try:Public Sub ScriviTesto4(ByVal datiIn As Byte())
Dim i As Int32If InvokeRequired Then Invoke(New Action(Of Byte())(AddressOf ScriviTesto4)) Return End If For i = 0 To (datiIn.Count - 1) TB1.Text &= Hex(datiIn(i)) & " " Next ScriviLabel(TB1.Text) 'write the textbox text to a label in the form TB1.Text &= vbCrLf
End Sub
Private Sub ScriviLabel(ByVal stringa As String)
Label1.Text = stringa
End SubWhat I can see in the debug is that
TB1.Text
,stringa
andLabel1.Text
all contains the right values but nothing appear in the window of my application. It seems to be a "visualization" problem, perhaps related to threads, but I'm not able to see the error. -
Eddy Vluggen wrote:
Did you create the textbox on the mainthread?
I added the textbox to the form1 in the designer, it should be in the main thread. In form1 I declared an instance of the class to manage the COM:
Dim NewCom As CommDev
In the Load event of the form I create the new object:
NewCom = New CommDev()
In the
New
function of the class some parameters are set, like baud rate, parity, etc. When I open the COM port, I call anInit
function that opens the COM port, sets buffer sizes, sets the device control block, sets timeouts, creates and starts the receiver thread.Eddy Vluggen wrote:
Can you write the string x to the debugger?
I used your code instead of mine and I can see the value of the string
x
, I mean that I can "add an expression control" (I don't know if this is the right translation of the italian "Aggiungi espressione di controllo" that appear in the right click menu over a variable during debug) to the stringx
and see its right value in the bottom windows of Visual Studio. Nothing appears in the textbox... I made also another try:Public Sub ScriviTesto4(ByVal datiIn As Byte())
Dim i As Int32If InvokeRequired Then Invoke(New Action(Of Byte())(AddressOf ScriviTesto4)) Return End If For i = 0 To (datiIn.Count - 1) TB1.Text &= Hex(datiIn(i)) & " " Next ScriviLabel(TB1.Text) 'write the textbox text to a label in the form TB1.Text &= vbCrLf
End Sub
Private Sub ScriviLabel(ByVal stringa As String)
Label1.Text = stringa
End SubWhat I can see in the debug is that
TB1.Text
,stringa
andLabel1.Text
all contains the right values but nothing appear in the window of my application. It seems to be a "visualization" problem, perhaps related to threads, but I'm not able to see the error.Can you add another label on the form?
Private Sub ScriviLabel(ByVal stringa As String)
Label1.Text = "Hello world"
Label2.Text = stringa
End SubThis is the point where I'd paranoidly check the colour of my font.
Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]
-
Can you add another label on the form?
Private Sub ScriviLabel(ByVal stringa As String)
Label1.Text = "Hello world"
Label2.Text = stringa
End SubThis is the point where I'd paranoidly check the colour of my font.
Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]
Hi Eddy, thanks for your efforts. I add the second label but no label takes the right content in the form; in the debug the Text properties contain my string and the "Hello world" string. I also call the
Refresh
method of labels and form but nothing changes. Before I did another project where I used theSerialPort
object of .NET, everything was in the form1 and I used theDataReceived
event of the COM to write in the textbox the received data, always using theInvoke
method, and everything was OK. In this project I don't use the SerialPort object but the API in coredll.dll (CreateFileW
,ReadFile
,SetCommMask
, etc.) because I need to catch different information from the COM port and all this is in a separate class/file. This is the main difference between the two projecs, in addition to the fact that one works and the other not... Sorry but I really don't know what is THE fundamental information I'm missing to solve this problem, if you have any questions, please feel free to ask.