Categories: MSDN / DotNet / Java / Scripts / Linux / PHP Ask - La ask - La Answer

Tree structure and threads in VB.NET

Hi all,
I am trying to communicate a serial device with my program. My program need to read the information coming through the device. Everything is OK so far. But I am doing this "information reading" using a thread.

Let me show some of the codes:

Dim thr As Threading.Thread = New Threading.Thread(AddressOf read_data)

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
thr.Start()
End Sub

When I click the button, the program reads the data. But when I click once more an exception occurs: Thread is running or terminated; it cannot restart.

As far as i see, The thread thr runs when i click the button and then it dies. When i click the button one more thread thr cannot be run again.

Consequently, I have to make the thread thr always run. How can I do this?
I have tried thr.abort() method. but it didn't work.

I need your help. I think a simple Try-Catch handling operation solves my problem, but i don't know how to write those codes. I don't understand Try-Catch operation so much. I am new on VB.NET.
[1172 byte] By [ozkanozlu] at [2007-11-11 10:25:34]
# 1 Re: Tree structure and threads in VB.NET
Once a thread finishes it can't be restarted. You need to create a new instance of the thread.

Try changing your code to this.

Dim thr As Threading.Thread
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
'Prevents multiple threads from being created
'You may want to kill the thread instead of returning. thr.abort would do that
'If you don't use the next line to abort or return then multiple threads will run but thr will only reference the newest
if thr isnot nothing andalso thr.IsAlive then return

'Create new instance of the thread
thr = New Threading.Thread(AddressOf read_data)
thr.Start()
End Sub
TwoFaced at 2007-11-11 20:47:51 >
# 2 Re: Tree structure and threads in VB.NET
Thank you for your interest. I am glad to get an answer. But this did not solve my problem. Because another exception occurs when I try the codes that you have sent.

let me show you whole program codes and you decide what to do:

Imports System.IO
Imports System.Threading.Thread

Public Class olcu
Dim thr As Threading.Thread 'This line was replaced with the line below.
'Dim thr As Threading.Thread = New Threading.Thread(AddressOf bilgial) 'Read_data thread
Dim gelenstr As String = "" 'A string object for coming data from port
Dim com1 As IO.Ports.SerialPort = My.Computer.Ports.OpenSerialPort("COM2", 9600, IO.Ports.Parity.None, 8, IO.Ports.StopBits.One) 'This line is for communication port declaration
Private Sub olcu_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
txttarih.Text = Now 'Gets the current date and time of measure of weight
'The recent measuring information is called from DB file
txtadi.Text = ds1.Tables("kimlik").Rows(0).Item(2)
txtyas.Text = ds1.Tables("kimlik").Rows(0).Item(3)
txtcins.Text = ds1.Tables("kimlik").Rows(0).Item(4)
txtboy.Text = ds1.Tables("kimlik").Rows(0).Item(5)
da_doldur("select * from kilo where kimlikno='" & Kullanici_Giris_Form.txtkimlik.Text & "' order by tarih desc", "kilo")
If ds1.Tables("kilo").Rows.Count > 0 Then
txtsontarih.Text = ds1.Tables("kilo").Rows(0).Item(2)
txtsonkilo.Text = ds1.Tables("kilo").Rows(0).Item(3) & "," & ds1.Tables("kilo").Rows(0).Item(4)
dgtarti.DataSource = ds1.Tables("kilo").DefaultView
dgtarti.Refresh()
Else
MsgBox("kullanıcıya ait tartı bilgisi bulunmamaktadır.") 'No informaiton about this user!
End If
End Sub

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
Me.Close()
End Sub

Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
yeni.ShowDialog() 'Not important you can pass this
End Sub
Public Sub bilgial() 'Data reading method starts here
Dim gelen As String = com1.ReadLine() 'Reads the line coming from the port to the String gelen
If gelen Is Nothing Then
txtkilo.Text = "Boş" '
Else
gelenstr &= gelen & vbCrLf
txtkilo.Text = gelen
End If
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

'Prevents multiple threads from being created
'You may want to kill the thread instead of returning. thr.abort would do that
'If you don't use the next line to abort or
'return then multiple threads will run but thr will only reference the newest
If thr IsNot Nothing AndAlso thr.IsAlive Then Return
thr = New Threading.Thread(AddressOf bilgial)
'Create new instance of the thread
thr.Start()

baglan() 'Database connection starts here
cmnd.CommandText = "insert into kilo(kimlikno,tarih,kilo,gram) values('" & Kullanici_Giris_Form.txtkimlik.Text & "','" & txttarih.Text & "'," & CType(txtkilo.Text, Integer) & "," & CType(txtgram.Text, Integer) & ")"
cmnd.ExecuteNonQuery()
baglanti_kes() 'Database connection terminated
MsgBox("yeni kilo bilgisi eklendi") 'New weight information added to DB!
da_doldur("select * from kilo where kimlikno='" & Kullanici_Giris_Form.txtkimlik.Text & "' order by tarih desc", "kilo")
If ds1.Tables("kilo").Rows.Count > 0 Then
txtsontarih.Text = ds1.Tables("kilo").Rows(0).Item(2)
txtsonkilo.Text = ds1.Tables("kilo").Rows(0).Item(3) & "," & ds1.Tables("kilo").Rows(0).Item(4)
dgtarti.DataSource = ds1.Tables("kilo").DefaultView
dgtarti.Refresh()
End If
txtkilo.Text = "" 'Cleans the weight textbox of Kilo
txtgram.Text = "" 'Cleans the weight textbox of gram
End Sub
End Class

You can see some strange definitions because of difference of my language. But I really need your help. And also I don't have any more time. In a week I have to write this program. I am a student and this is not a commercial thing. Please I am begging you. :o
ozkanozlu at 2007-11-11 20:48:53 >
# 3 Re: Tree structure and threads in VB.NET
No need to beg I'm always happy to help :) The code I gave you does work in my tests so I'm not sure it's that code that's causing a problem. What exception are you getting? Where and when does it happen? I assume it happens when button1 is clicked, but are you positive it's related to my code?

thr = New Threading.Thread(AddressOf bilgial)

Where is the method bilgial? I assume it's in a module somewhere because I didn't notice it anywhere in your class. If it's somewhere else then please post that method so I can see if something might be going wrong with it.

**EDIT**
Sorry, I missed the method bilgial the first time I read through your code. I have a feeling I know the problem. You can't update UI elements from a different thread then the one it was created on. Are you getting an exception similiar to this?

Cross-thread operation not valid: Control 'TextBox1' accessed from a thread other than the thread it was created on.

If that's not the current problem then it will be :) If it is we can easily fix that. Just get back to me on the exception your getting and I think we can figure this out.
TwoFaced at 2007-11-11 20:49:47 >
# 4 Re: Tree structure and threads in VB.NET
I wrote "If thr IsNot Nothing AndAlso thr.IsAlive Then thr.Abort()" and then when I click Button it records the coming data. But I click one more time an exception occurs: "Safe handle has been closed" which is titled as ObjectDisposed Exception unhadled

I wrote "If thr IsNot Nothing AndAlso thr.IsAlive Then Return"
and then when I click Button it records the coming data. But I click one more time after recording. It does nothing.
ozkanozlu at 2007-11-11 20:50:55 >
# 5 Re: Tree structure and threads in VB.NET
I wrote "If thr IsNot Nothing AndAlso thr.IsAlive Then thr.Abort()" and then when I click Button it records the coming data. But I click one more time an exception occurs: "Safe handle has been closed" which is titled as ObjectDisposed Exception unhadled

I wrote "If thr IsNot Nothing AndAlso thr.IsAlive Then Return"
and then when I click Button it records the coming data. But I click one more time after recording. It does nothing.Nice, I think that information helped me isolate the problem. I tried testing your code and I believe if com1.readline has nothing to read it just waits and never returns. You said it read the information but are you sure? I don't think it did. In my test, code after that line never executed. When I tried running the thread again my procedure exited because the thread was still alive, which is exactly what happend when you used "If thr IsNot Nothing AndAlso thr.IsAlive Then return". However, when you tried using "If thr IsNot Nothing AndAlso thr.IsAlive Then thr.abort" you got an error. I also recieved the same error and it wasn't due to my code. I think when the thread was killed the com1 object was still trying to read the data. When the thread is suddenly aborted you get an error from com1. Try the following change.

Public Sub bilgial() 'Data reading method starts here
Dim gelen As String = com1.ReadLine 'Reads the line coming from the port to the String gelen

'If I am right this code should never execute.
MsgBox("Data was read") 'Display message proving we got this far
If gelen Is Nothing Then
txtkilo.Text = "Boş" '
Else
gelenstr &= gelen & vbCrLf
txtkilo.Text = gelen
End If
End SubBecause I don't really know what com1.Readline is supposed to do I can't really help. Is it supposed to just wait for information? If that's the case you don't need to run the thread again until it got the data. In that case just use "If thr IsNot Nothing AndAlso thr.IsAlive Then return". This should exit the procedure because the thread is alive and still waiting for information. It may not be reading from your seriai port correctly, which could also be why it never returns. One change I made was to set a timeout of 1 second form the com1 object. Public Sub bilgial() 'Data reading method starts here
'Sets a time out of 1 second
com1.ReadTimeout = 1000

Dim gelen As String = Nothing
Try
gelen = com1.ReadLine 'Reads the line coming from the port to the String gelen
Catch ex As System.TimeoutException
'Catch the timeout exception
End Try

If gelen Is Nothing Then
txtkilo.Text = "Boş" '
Else
gelenstr &= gelen & vbCrLf
txtkilo.Text = gelen
End If
End SubWith the above code I give the com1 object a maximum of a second to read the data. If it can't an exception is thrown which I catch in the try catch block. The procedure should then finish normally and the thread will die allowing you to start it again.
TwoFaced at 2007-11-11 20:51:55 >
# 6 Re: Tree structure and threads in VB.NET
OK! That is it! I did it! As you said 2Faced, I wrote the codes below. And everything is now OK. :WAVE:

if thr isnot nothing andalso thr.IsAlive then return

'Create new instance of the thread
thr = New Threading.Thread(AddressOf read_data)
thr.Start()

Thank you very much.
ozkanozlu at 2007-11-11 20:52:55 >