From: eBob.com on 9 Dec 2009 16:14 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
From: Armin Zingler on 9 Dec 2009 17:55 eBob.com schrieb: > 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
From: eBob.com on 9 Dec 2009 22:17 "Armin Zingler" <az.nospam(a)freenet.de> wrote in message news:OvMuVLSeKHA.1596(a)TK2MSFTNGP06.phx.gbl... > eBob.com schrieb: >> 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 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
From: Armin Zingler on 9 Dec 2009 22:50 eBob.com schrieb: > 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
From: eBob.com on 10 Dec 2009 10:17
"Armin Zingler" <az.nospam(a)freenet.de> wrote in message news:uwm5ZwUeKHA.1596(a)TK2MSFTNGP06.phx.gbl... > eBob.com schrieb: >> 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 > 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 |