Loosing reference to Thread

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

I need to have a thread run as long as it needs to, and not stop until it is cancelled by either closing the application or manually be stopped. It is simply pinging a machine to see what the connection speed is. The ping code is not the problem, as I have used it to get the speeds before, and it is solid

What happens is that after the thread has been running awhile, it just stops. I cannot stop it, but when I restart the thread, it is fine. I don't mind restarting the thread, but I want it to do it automatically. Is there some code that I can put in to detect if the thread has gone awry?

I have a button on the form that simply starts and stops the thread. If I leave the thread running too long, the code stops to work. When that happens, I stop the thread, and I get the 'Thread cannot be stopped' message box (see code below). Then I can restart the thread

I used the code samples that the MSDN has to make it work. Here is the code I have now

Public CancelThread As New System.Threading.ManualResetEvent(False
Public ThreadisCanceled As New System.Threading.ManualResetEvent(False

Private Sub SomeLongTask(
' Run code until CancelThread is set
While Not CancelThread.WaitOne(0, False)
' Do some kind of task here
System.Threading.Thread.Sleep(CSng(txtPingDelay.Text) * 1000) 'txtpingdelay = .
ThreadPing(
End Whil

If CancelThread.WaitOne(0, False) The
'Acknowledge that the ManualResetEvent CancelThread is set
ThreadisCanceled.Set(
End I
End Su

Public Sub StartTask(
' Starts a new thread
Dim th As New System.Threading.Thread(AddressOf SomeLongTask
CancelThread.Reset(
ThreadisCanceled.Reset(
th.Start(
End Su

Public Sub CancelTask(
' Stops any threads started by the StartTask procedure
' Notice that this thread both receives and sends
' synchronization events to coordiante the threads.
CancelThread.Set() ' Set CancelThread to ask the thread to stop
If ThreadisCanceled.WaitOne(4000, False) The
' Wait up to 4 seconds for the thread to
' acknowledge that it has stopped
Els
MsgBox("The thread could not be stopped."
End I
End Su

Private Sub ThreadPing(

Dim Sum As Int32 =

Dim myPinger As IDOTPing.Ping = New IDOTPing.Pin
Dim ret As Int3

If txtHost.Text.Length < 1 The
ret = myPinger.PingHost("localhost"
Els
ret = myPinger.PingHost(txtHost.Text
End I

PingAverage.Enqueue(ret
If PingAverage.Count > PingCount Then PingAverage.Dequeue(

Dim myEnum As IEnumerator = PingAverage.GetEnumerato
While myEnum.MoveNex
Sum = Sum + CLng(myEnum.Current
Console.WriteLine(myEnum.Current
End Whil
lblResult.Text = "Connection Speed: " & ret.ToString & " MS

Sum = Sum / PingAverage.Coun
Label2.Text = "Average for last " & PingAverage.Count & " pings: " & Sum & " MS

If Sum > pgPing.Maximum The
pgPing.Value = pgPing.Maximu
ElseIf Sum < 0 The
pgPing.Value =
Els
pgPing.Value = pgPing.Maximum - Su
End I

End Su

I hope someone can help me out. I have not had a lot of luck lately getting any help from this newsgroup. Kind of disappointing when you need the help

Brad Simon
 
I think your subject says it all, "Loosing reference to a thread", though
I've never let a thread hang in the air and see if it continues working, so
I may be wrong.
In your sub StartTask you declare a thread on the stack. When StartTask is
done, there is no reference to the thread any more, ready to be garbage
collected, I would say.
So declare it up top in your form/class, so that the reference to it is
always there. If there is not something wrong with your thread logic itself,
it should continue to work.

Brad Simon said:
I need to have a thread run as long as it needs to, and not stop until it
is cancelled by either closing the application or manually be stopped. It
is simply pinging a machine to see what the connection speed is. The ping
code is not the problem, as I have used it to get the speeds before, and it
is solid.
What happens is that after the thread has been running awhile, it just
stops. I cannot stop it, but when I restart the thread, it is fine. I
don't mind restarting the thread, but I want it to do it automatically. Is
there some code that I can put in to detect if the thread has gone awry?
I have a button on the form that simply starts and stops the thread. If I
leave the thread running too long, the code stops to work. When that
happens, I stop the thread, and I get the 'Thread cannot be stopped' message
box (see code below). Then I can restart the thread.
I used the code samples that the MSDN has to make it work. Here is the code I have now:

Public CancelThread As New System.Threading.ManualResetEvent(False)
Public ThreadisCanceled As New System.Threading.ManualResetEvent(False)

Private Sub SomeLongTask()
' Run code until CancelThread is set.
While Not CancelThread.WaitOne(0, False)
' Do some kind of task here.
System.Threading.Thread.Sleep(CSng(txtPingDelay.Text) * 1000) 'txtpingdelay = .5
ThreadPing()
End While

If CancelThread.WaitOne(0, False) Then
'Acknowledge that the ManualResetEvent CancelThread is set.
ThreadisCanceled.Set()
End If
End Sub

Public Sub StartTask()
' Starts a new thread.
Dim th As New System.Threading.Thread(AddressOf SomeLongTask)
CancelThread.Reset()
ThreadisCanceled.Reset()
th.Start()
End Sub

Public Sub CancelTask()
' Stops any threads started by the StartTask procedure.
' Notice that this thread both receives and sends
' synchronization events to coordiante the threads.
CancelThread.Set() ' Set CancelThread to ask the thread to stop.
If ThreadisCanceled.WaitOne(4000, False) Then
' Wait up to 4 seconds for the thread to
' acknowledge that it has stopped.
Else
MsgBox("The thread could not be stopped.")
End If
End Sub

Private Sub ThreadPing()

Dim Sum As Int32 = 0

Dim myPinger As IDOTPing.Ping = New IDOTPing.Ping
Dim ret As Int32

If txtHost.Text.Length < 1 Then
ret = myPinger.PingHost("localhost")
Else
ret = myPinger.PingHost(txtHost.Text)
End If

PingAverage.Enqueue(ret)
If PingAverage.Count > PingCount Then PingAverage.Dequeue()

Dim myEnum As IEnumerator = PingAverage.GetEnumerator
While myEnum.MoveNext
Sum = Sum + CLng(myEnum.Current)
Console.WriteLine(myEnum.Current)
End While
lblResult.Text = "Connection Speed: " & ret.ToString & " MS"

Sum = Sum / PingAverage.Count
Label2.Text = "Average for last " & PingAverage.Count & " pings: " & Sum & " MS"

If Sum > pgPing.Maximum Then
pgPing.Value = pgPing.Maximum
ElseIf Sum < 0 Then
pgPing.Value = 0
Else
pgPing.Value = pgPing.Maximum - Sum
End If

End Sub

I hope someone can help me out. I have not had a lot of luck lately
getting any help from this newsgroup. Kind of disappointing when you need
the help.
 
Brad Simon said:
I need to have a thread run as long as it needs to, and not stop
until it is cancelled by either closing the application or manually
be stopped. It is simply pinging a machine to see what the
connection speed is.

Why create your own thread to do this?

It's a perfect use of a System.Threading.Timer class. Let the Framework
manage the thread ownership issues, and the "wake up periodically and do
something" issues. The system threadpool is your friend (usually).

This removes from you the burden of: (1) creating a thread, (2) shutting
down a thread, (3) making sure a thread keeps running, (4) restarting the
thread if something happens to it.
 
Brad Simon said:
What happens is that after the thread has been running awhile, it just
stops.

The problem you're most likley having is that you're getting an exception
generated during your Ping routine. Because you have no exception handler in
your thread proc, the exception is caught by the framework. This has the
side effect of having your thread "disappear". Put a Try/Catch around the
entire thread function.

I would bet that, when you're in this state, if you look at the "threads"
window in the debugger, you won't see your thread showing up. To verify
this, set the name of the thread (myThread.Name) when you create it, and
make sure you can see it in the thread debug window. Then make sure it's
gone when you have the problem.

.... but you should stil probably use the Threading.Timer class.
 
The Timer does work fine, but in the final applicaiton I am useing the offline smart client application block, and the timer does not work at all in it (Argh)

I did find that it was the ping causing the problem, however there was no error, it was just a ping that took a long time, too long, and it the thread lost it

The solution was to call an Asynchronous method inside the thread, and it works fine (I did that after trying all of the timer stuff)

If anyone is interested, I can put up some code on my personal site to show how all of it worked. Send me an e-mail if you are interested

Thanks for everyone's help!!! It did help me to look at the problem in a different light.
 
Chris Mullins said:
Why create your own thread to do this?

It's a perfect use of a System.Threading.Timer class. Let the Framework
manage the thread ownership issues, and the "wake up periodically and do
something" issues. The system threadpool is your friend (usually).

This removes from you the burden of: (1) creating a thread, (2) shutting
down a thread, (3) making sure a thread keeps running, (4) restarting the
thread if something happens to it.

However, it really isn't designed for long-running tasks. If you start
putting long-running tasks in it, other things which rely on the
thread-pool could block, possibly even deadlocking your app.

I've mostly written my own ThreadPool class so that "user threads" can
make sure they won't interfere with system uses of the system thread
pool - that could help in situations like this,.
 
Back
Top