How to restart "Stopped" thread?

  • Thread starter Thread starter Brett
  • Start date Start date
B

Brett

I have a second thread, t2, that errors out and will stop. It's status is
then "Stopped". I try to start t2 from thread 1, t1, by checking

If t2.threadstate = "Stopped" Then
t2.start()

However, this throws and error:

System.Threading.ThreadStateException: Thread is running or terminated; it
can not restart.

How can this thread restart?

Also, how to I put a thread in a "Stopped" state? Is this through
thread.abort()?

Thanks,
Brett
 
Typically you would start a new thread. thread.abort will not allow that
thread ever to start again. I think if you do a thread.suspend you can
restart it.

Chris
 
Brett said:
I have a second thread, t2, that errors out and will stop. It's status is
then "Stopped". I try to start t2 from thread 1, t1, by checking

If t2.threadstate = "Stopped" Then
t2.start()

However, this throws and error:

System.Threading.ThreadStateException: Thread is running or terminated; it
can not restart.

How can this thread restart?

If a thread's state is 'Stopped', the thread is either responding to an
'Abort' request or it is terminated. Create a new thread instead of dealing
with the stopped thread.
Also, how to I put a thread in a "Stopped" state? Is this through
thread.abort()?

Yes.
 
I see. Right now I do this to create the new thread initially when Form1
loads:

Public NewThread As New Class1
Public t As System.Threading.Thread = New System.Threading.Thread(New
System.Threading.ThreadStart(AddressOf NewThread.callSomeSub))

The occurs outside of any sub. I have a button to do t.start() initially.
Once the thread is "stopped" and cannot be restarted, you're saying I need
to create another/new thread. How can I do that in the sub() of this
button? I can't declare Public because I'll get:

Public is not valid on local variable declaration

I need the new thread to be public so sub()s in Form1 can access it.

Thanks,
Brett
 
I'm a little confused. You need any procedure in Form1 to be able to access
a thread. Make the reference to the thread public in form1 then. I think
this is what you need to do.


Note: This code isn't perfect, just trying to show the idea. There are
examples in MSDN you can look at.
Public Class Form1

Public t As System.Threading.Thread

Sub StartThread
t = New System.Threading.Thread(New
System.Threading.ThreadStart(AddressOf NewThread.callSomeSub))
t.start
End Sub
sub SomeSubInForm1
t.abort()
Me.StartThread()
end sub
End Class

Public Class Class1
Public Static Sub callSomeSub
End Class
End Class
 
I see. I was trying to declare t twice when all I need to do was give it a
value.

Thanks,
Brett
 
If the thread2 is suspended, how can I kill it? Say my application is
shutting down, I can do t2.abort() but that will throw an error, which I'll
need to catch. I can do nothing and just shut the app down. However, the
thread doesn't remove itself from memory.

I have to do a
t2.resume()
t2.sleep(x)
t2.abort()

for it to remove from memory.

Thanks,
Brett
 
Brett said:
If the thread2 is suspended, how can I kill it? Say my application is
shutting down, I can do t2.abort() but that will throw an error, which
I'll need to catch. I can do nothing and just shut the app down.
However, the thread doesn't remove itself from memory.

Set the thread's 'IsBackground' property to 'True'.
 
Herfried K. Wagner said:
Set the thread's 'IsBackground' property to 'True'.
When I put a thread to sleep, t.sleep(x), how can I find out the current
value of x? Say x is initially 60000 (one minute). I do t.sleep(x). After
some number of seconds but less than one minute, I'd like to know the x
sleep value (for lack of better words). Perhaps it is at 20 seconds or 36
seconds. Even better, I'd like to display a real time count up/down of the
seconds in a textbox. Any suggestions?

Thanks,
Brett
 
Brett said:
When I put a thread to sleep, t.sleep(x), how can I find out the current
value of x? Say x is initially 60000 (one minute). I do t.sleep(x).
After some number of seconds but less than one minute, I'd like to know
the x sleep value (for lack of better words). Perhaps it is at 20 seconds
or 36 seconds. Even better, I'd like to display a real time count up/down
of the seconds in a textbox.

Add a 'System.Windows.Forms.Timer' to your form, place the code to update
the time in its 'Tick' event handler and use
'Control.Invoke'/'Control.BeginInvoke' to enable it from within the 2nd
thread directly before calling 'Sleep' on the thread.
 
Herfried K. Wagner said:
Add a 'System.Windows.Forms.Timer' to your form, place the code to update
the time in its 'Tick' event handler and use
'Control.Invoke'/'Control.BeginInvoke' to enable it from within the 2nd
thread directly before calling 'Sleep' on the thread.

I do have a timer on Form1 to poll t2.threadstate from Form1. I then
display this value every second as a string in a label. Say the timer is
named tmr1. Are you saying to do tmr1.Invoke/tmr1.BeginInvoke? The timer
doesn't have those methods.

I think if you knew I had a timer, you are saying to do this:

Public Class Class1

Form1.DoSleepCount = 1
Thread.CurrentThread.sleep(x)
Form1.DoSleepCount = 0
Form1.Label2.Text = ""



Public Class Form1

Public count as Integer = 1
Public Shared DoSleepCount as Integer = 0

Public Sub SleepCount()
count += 1
Form1.Label2.Text = count.ToString
End Sub

Private Sub tmr1
-- do something here--
If DoSleepCount = 1 Then
SleepCount()
End If
End Sub

That seem correct?

Thanks,
Brett
 
Brett said:
I do have a timer on Form1 to poll t2.threadstate from Form1. I then
display this value every second as a string in a label. Say the timer is
named tmr1. Are you saying to do tmr1.Invoke/tmr1.BeginInvoke? The
timer doesn't have those methods.

You are right, my bad. 'Timer' does not have these methods because it's not
a control. So, instead, add methods or a property to your form that will
enable/disable the timer, and call these methods or set this property by
using the form's 'Invoke'/'BeginInvoke' method. Instance members of
'System.Windows.Forms.Timer' are not safe for multithreading, so you cannot
access them directly from within an other thread.
 
Herfried K. Wagner said:
You are right, my bad. 'Timer' does not have these methods because it's
not a control. So, instead, add methods or a property to your form that
will enable/disable the timer, and call these methods or set this property
by using the form's 'Invoke'/'BeginInvoke' method. Instance members of
'System.Windows.Forms.Timer' are not safe for multithreading, so you
cannot access them directly from within an other thread.

Well, using the code I posted, the timer won't actually be accessed from
another thread. Just Form1's DoSleepCount var and Form1.Label2.Text object.
That should be safe correct?

Thanks again,
Brett
 
Brett,
Well, using the code I posted, the timer won't actually be accessed from
another thread. Just Form1's DoSleepCount var and Form1.Label2.Text
object. That should be safe correct?
Form1.Label2 is a control, it's property .Text cannot be accessed safely
from another thread.

Hope this helps
Jay
 
Jay B. Harlow said:
Brett,
Form1.Label2 is a control, it's property .Text cannot be accessed safely
from another thread.

Hope this helps
Jay

Why is that?

Thanks,
Brett
 
Brett said:
Why is that?

That's because instance members of Windows Forms controls are not safe for
multithreading (... or do you want to know the reasons for that?). You can
use 'Control.Invoke'/'Control.BeginInvoke' to access the label's 'Text'
property to overcome this limitation.
 
Brett,
It uses Win32 controls underneath, Win32 controls are not designed to be
thread safe.

Most of the time you do not need your objects (both your the classes you
define & Win32 controls) to be thread as, as only one thread will access the
object at a time. Only in the case, such as this, where you want to update
one object from another thread do you need to worry about thread safety. The
designers of Win32 & .NET decided that its rare to access a control from
another thread, so they did not design safety in. If they did design thread
safety in, then each method would effectively need a SyncLock statement in
it, all this SyncLock statements would have a negative impact on
non-multithreaded applications...

Also think about in your case you only want to update Text, if Label were
thread safe *ALL* properties would need to be thread safe. Do you want a
performance hit on all methods simply to update Text? Would it not be better
to write special code (Control.BeginInvoke) to update just the Text
property?

Hope this helps
Jay
 
Jay B. Harlow said:
designers of Win32 & .NET decided that its rare to access a control from
another thread, so they did not design safety in. If they did design
thread safety in, then each method would effectively need a SyncLock
statement in it, all this SyncLock statements would have a negative impact
on non-multithreaded applications...

[For the records:]

Not only Windows Forms made this decision, you will rarely find a
multithreading-safe GUI package:

Multithreaded toolkits: A failed dream?
<URL:http://weblogs.java.net/blog/kgh/archive/2004/10/multithreaded_t.html>
 
Herfried K. Wagner said:
Jay B. Harlow said:
designers of Win32 & .NET decided that its rare to access a control from
another thread, so they did not design safety in. If they did design
thread safety in, then each method would effectively need a SyncLock
statement in it, all this SyncLock statements would have a negative
impact on non-multithreaded applications...

[For the records:]

Not only Windows Forms made this decision, you will rarely find a
multithreading-safe GUI package:

Multithreaded toolkits: A failed dream?
<URL:http://weblogs.java.net/blog/kgh/archive/2004/10/multithreaded_t.html>

What if I do this:

Form1.DoSleepCount = 1
Thread.CurrentThread.sleep(x)
Form1.DoSleepCount = 0

Where
Form1.Label2.Text = ""

is inside of DoSleepCount. Is that thread safe?

I suppose its more that I don't understand the concept of
Label2.invoke/begininvoke. Can you show some sample code?

Thanks,
Brett
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top