Why Won't My Thread Abort

  • Thread starter Thread starter eBob.com
  • Start date Start date
E

eBob.com

I've written some simple multi-threading code so that I can play with
Aborting and restarting threads. The Abort seems to happen according to
MsgBoxes in the code, but the thread then seems to switch back to a Running
state and is therefore not re-started.

The code is below. In more detail ... The code in StartMainThread (which is
not the UI thread) starts two threads, Thread2 and Thread3. MsgBoxes
indicate that they start. All they do is wait for 30 seconds. But if they
Catch an Exception they wake up their parent, i.e. the code in
StartMainThread, which will restart the thread if its state is Aborted,
AbortRequested, or Stopped. Code not shown below issues the Thread.Abort
for Thread2 and the MsgBox in StartSubThread shows its state as
AbortRequested. Then the code in StartMainThread does wake up, but
according to the MsgBox there is seeing the thread's state as Running. How
can that be? What am I missing?

Thanks, Bob

Sub StartMainThread()
Dim MeThread As Threading.Thread
MeThread = Threading.Thread.CurrentThread
MsgBox(MeThread.Name & " started, TID = " &
MeThread.ManagedThreadId.ToString)
MainWaitHandle = New AutoResetEvent(False)
Thread2 = New Threading.Thread(AddressOf StartSubThread)
Thread2.Name = "Thread2"
Thread2.Start()
Thread3 = New Threading.Thread(AddressOf StartSubThread)
Thread3.Name = "Thread3"
Thread3.Start()
Do While True
MainWaitHandle.WaitOne() ' wait for either thread to siginal
MsgBox("Main woke up")
MsgBox("thread2.threadstate = " & MeThread.ThreadState.ToString)
If (Thread2.ThreadState Or (ThreadState.Aborted Or _
ThreadState.AbortRequested Or
ThreadState.Stopped)) = 1 Then
MsgBox("Thread2 kaput, restarting it.")
Thread2 = New Threading.Thread(AddressOf StartSubThread)
Thread2.Name = "Thread2"
Thread2.Start()
End If
If (Thread3.ThreadState Or (ThreadState.Aborted Or _
ThreadState.AbortRequested Or
ThreadState.Stopped)) = 1 Then
MsgBox("Thread3 kaput, restarting it.")
Thread3 = New Threading.Thread(AddressOf StartSubThread)
Thread3.Name = "Thread3"
Thread3.Start()
End If
Loop
End Sub

Sub StartSubThread()
Dim MeThread As Threading.Thread
MeThread = Threading.Thread.CurrentThread
MsgBox(MeThread.Name & " started, TID = " &
MeThread.ManagedThreadId.ToString)
Try
Thread.Sleep(30000)
Catch ex As Exception
MsgBox("Exception Caught: " & ex.ToString)
MsgBox(MeThread.ThreadState.ToString)
MainWaitHandle.Set()
End Try
MsgBox(MeThread.Name & " ending, TID = " &
MeThread.ManagedThreadId.ToString)

End Sub
 
eBob.com said:
If (Thread2.ThreadState Or (ThreadState.Aborted Or _
ThreadState.AbortRequested Or
ThreadState.Stopped)) = 1 Then

Before examining the problem, what do you expect the line above to do?
If you want to check some flags, use the And operator with the pattern.

(The "1" seems to be ThreadState.StopRequested)


_If_ you want to check if the state is one of the three states, it should be:

If (thread2.ThreadState _
And _
(ThreadState.Aborted Or ThreadState.AbortRequested Or ThreadState.Stopped)) _
<> ThreadState.Running Then 'or: ......<> 0
 
Armin Zingler said:
Before examining the problem, what do you expect the line above to do?
If you want to check some flags, use the And operator with the pattern.

(The "1" seems to be ThreadState.StopRequested)


_If_ you want to check if the state is one of the three states, it should
be:

If (thread2.ThreadState _
And _
(ThreadState.Aborted Or ThreadState.AbortRequested Or
ThreadState.Stopped)) _
<> ThreadState.Running Then 'or: ......<> 0

Hi Armin,

Thanks for looking at this. It turns out that the code I posted had two
really stupid mistakes. The one you identified and another one which
resulted in the code looking at the wrong Thread instance. The thread which
I abort has a ThreadState of Stopped by the time the code in the parent
thread (i.e. the code in StartMainThread)looks at it. That was a typo type
mistake. The mistake you identified was plain stupidity. I have no idea
what I was thinking. But I confess that manipulating bit masks in higher
level languages always throws me.

The idea, in words, is to restart the thread if it has Stopped or is about
to stop.

What I've come up with now, and it seems to work, is ...

With Thread2
If ((.ThreadState And ThreadState.Aborted) = ThreadState.Aborted _
Or (.ThreadState And ThreadState.AbortRequested) =
ThreadState.AbortRequested _
Or (.ThreadState And ThreadState.Stopped) = ThreadState.Stopped)
Then
MsgBox("Thread2 kaput, restarting it.")
Thread2 = New Threading.Thread(AddressOf StartSubThread)
.Name = "Thread2"
.Start()
End If
End With

It looks pretty "wordy" to me but it also seems clear as to what it's doing.

BUT ... I get a run time error on the statement assigning the Name! The
message is "This property has already been set and cannot be modified." The
statement above the Name assignment creates a new instance. How can .NET
think that any property has already been set? If I use a MsgBox to look at
the Name property immediately after creating the new instance it's null,
i.e. a 0 length string. I've just begun to research this and I do get some
hits on the error message but they are from 2007.

Thanks again for your help Armin. If you have any thoughts on the latest
error I'd sure appreciate them.

Bob
 
eBob.com said:
What I've come up with now, and it seems to work, is ...

With Thread2
If ((.ThreadState And ThreadState.Aborted) = ThreadState.Aborted _
Or (.ThreadState And ThreadState.AbortRequested) =
ThreadState.AbortRequested _
Or (.ThreadState And ThreadState.Stopped) = ThreadState.Stopped)
Then
MsgBox("Thread2 kaput, restarting it.")
Thread2 = New Threading.Thread(AddressOf StartSubThread)
.Name = "Thread2"
.Start()
End If
End With

It looks pretty "wordy" to me but it also seems clear as to what it's doing.

BUT ... I get a run time error on the statement assigning the Name! The
message is "This property has already been set and cannot be modified." The
statement above the Name assignment creates a new instance. How can .NET
think that any property has already been set?

The "With Thread2" statement refers to the the Thread object assigned to
variable Thread2 at the moment of execution of the With-statement.
You must use "Thread2.Name =..." instead to refer to the new instance.

"With" is not only a syntactical simplification. These three lines...

With Thread2
.name = ...
end with

are _not_ equal to

Thread2.name = ...

but they are equal to

dim tmp as Thread
tmp = Thread2
tmp.name = ...




Reason: "With" is usually/also used to optimize expressions like this one:

object.prop.prop.prop1 = value1
object.prop.prop.prop2 = value2

If this simplification...

With object.prop.prop
.prop1 = value1
.prop2 = value2
end With

.... was only a simplification in syntax, it would be translated to

object.prop.prop.prop1 = value1
object.prop.prop.prop2 = value2

But then it wouldn't be an improvement at all, in opposite to the actual translation to

dim tmp as whatever

tmp = object.prop.prop
tmp.prop1 = value1
tmp.prop2 = value2

Only the latter version makes it an optimization.
 
Armin Zingler said:
The "With Thread2" statement refers to the the Thread object assigned to
variable Thread2 at the moment of execution of the With-statement.
You must use "Thread2.Name =..." instead to refer to the new instance.

"With" is not only a syntactical simplification. These three lines...

With Thread2
.name = ...
end with

are _not_ equal to

Thread2.name = ...

but they are equal to

dim tmp as Thread
tmp = Thread2
tmp.name = ...




Reason: "With" is usually/also used to optimize expressions like this one:

object.prop.prop.prop1 = value1
object.prop.prop.prop2 = value2

If this simplification...

With object.prop.prop
.prop1 = value1
.prop2 = value2
end With

... was only a simplification in syntax, it would be translated to

object.prop.prop.prop1 = value1
object.prop.prop.prop2 = value2

But then it wouldn't be an improvement at all, in opposite to the actual
translation to

dim tmp as whatever

tmp = object.prop.prop
tmp.prop1 = value1
tmp.prop2 = value2

Only the latter version makes it an optimization.

WOW! Thank you so much Armin. It would have taken me days to figure that
out. It LOOKS like a purely syntatic thing and that is the way I've always
used it.

Thank you again. I am really grateful for the help you give me.

Bob
 
eBob.com said:
WOW! Thank you so much Armin. It would have taken me days to figure that
out. It LOOKS like a purely syntatic thing and that is the way I've always
used it.

Thank you again. I am really grateful for the help you give me.

Always a pleasure! :-)
 
Back
Top