Why does .ThreadState.ToString Behave This Way?
-
Hi, all. Once again, vb.Net shows how convoluted it can be. Or I'm just stupid. Assume I have a background thread running. Then, if in the Immediate window, I type in
?m_Thread.ThreadState.ToString
I get back, "Background". But if I first assign ThreadState to a string variable:
Dim ThreadState\_str As String ThreadState\_str = m\_Thread.ThreadState.ToString
and type in
?ThreadState_str
I get back:
"Background, WaitSleepJoin"
What is going on here?!
-
Hi, all. Once again, vb.Net shows how convoluted it can be. Or I'm just stupid. Assume I have a background thread running. Then, if in the Immediate window, I type in
?m_Thread.ThreadState.ToString
I get back, "Background". But if I first assign ThreadState to a string variable:
Dim ThreadState\_str As String ThreadState\_str = m\_Thread.ThreadState.ToString
and type in
?ThreadState_str
I get back:
"Background, WaitSleepJoin"
What is going on here?!
ThreadState is an enumeration. In the first case, the thread has the
IsBackground
set, which shows up at Background at the Thread.ThreadState property. In the second state, the thread is blocked by a wait or join. Such behavior of the ToString method is due to the FlagsAttribute[^] and the Enum.ToString method[^]. See ThreadState@MSDN[^] for more details.Beauty cannot be defined by abscissas and ordinates; neither are circles and ellipses created by their geometrical formulas.
-
ThreadState is an enumeration. In the first case, the thread has the
IsBackground
set, which shows up at Background at the Thread.ThreadState property. In the second state, the thread is blocked by a wait or join. Such behavior of the ToString method is due to the FlagsAttribute[^] and the Enum.ToString method[^]. See ThreadState@MSDN[^] for more details.Beauty cannot be defined by abscissas and ordinates; neither are circles and ellipses created by their geometrical formulas.
-
You should not rely on the string representation of an object they are likely to change. You should evaluate the values.
Beauty cannot be defined by abscissas and ordinates; neither are circles and ellipses created by their geometrical formulas.
-
You should not rely on the string representation of an object they are likely to change. You should evaluate the values.
Beauty cannot be defined by abscissas and ordinates; neither are circles and ellipses created by their geometrical formulas.
That's what is annoying about it. When you take the string representation of an object at any given moment via the ToString method, nothing should change in that moment, and it should be valid as a value. For in that moment, you pulled out a piece of information that in many cases will be used immediately. If vb allows the printing of a value from ThreadState, then that should be the same thing as "printing" it to a string which is nothing more than a storage spot for the same thing. It should be, anyway.
-
That's what is annoying about it. When you take the string representation of an object at any given moment via the ToString method, nothing should change in that moment, and it should be valid as a value. For in that moment, you pulled out a piece of information that in many cases will be used immediately. If vb allows the printing of a value from ThreadState, then that should be the same thing as "printing" it to a string which is nothing more than a storage spot for the same thing. It should be, anyway.
Schrodinger's cat... the very act of observing the sate can chance the state.
-
That's what is annoying about it. When you take the string representation of an object at any given moment via the ToString method, nothing should change in that moment, and it should be valid as a value. For in that moment, you pulled out a piece of information that in many cases will be used immediately. If vb allows the printing of a value from ThreadState, then that should be the same thing as "printing" it to a string which is nothing more than a storage spot for the same thing. It should be, anyway.
It makes complete sense and is not convoluted at all. By the way, it's not VB doing it, it's Visual Studios debugger and YOU! When you stop the app, the debugger stops all the threads in it, therefor modifying their state. But, it's not entirely stopped. When you get the value of a property, the debugger executes the property Get code, so the thread isn't entirely stopped. As was already mentioned, the act of viewing an object changes it's state! You're still doing a fair bit of bashing of VB.NET/.NET without trying to understand what's going on under the covers and why.
A guide to posting questions on CodeProject[^]
Dave Kreskowiak -
It makes complete sense and is not convoluted at all. By the way, it's not VB doing it, it's Visual Studios debugger and YOU! When you stop the app, the debugger stops all the threads in it, therefor modifying their state. But, it's not entirely stopped. When you get the value of a property, the debugger executes the property Get code, so the thread isn't entirely stopped. As was already mentioned, the act of viewing an object changes it's state! You're still doing a fair bit of bashing of VB.NET/.NET without trying to understand what's going on under the covers and why.
A guide to posting questions on CodeProject[^]
Dave KreskowiakSorry for the frustration showing. But in an attempt to understand what is going on, here is the way threads should behave the way I understand it. Let's say I have two threads that calculate the results of some equations:
Thread-1 produces 1........2....... 4.......8........16.......32 Thread-2 produces 1.5....1.837....2.49....3.929....7.789....21.737
1. All threads are suspended at time (t). Since Thread-1 is iterating faster than Thread-2, due to simpler equations, Thread-1 makes more progress than Thread-2, by time (t). 2. Since the exact moments that Threads 1 & 2 will be suspended will most likely occur asynchronously, this may add further uncertainty as to when Threads 1 & 2 will actually come to a halt. This could result in another complete iteration "slipping through" in either thread. But most likely, each thread will be suspended somewhere in the middle of an iteration. Nonetheless, the output values will not change until an iteration is completed. 3. At time (t + DELTAt), queries are made of the results from Threads 1 & 2. Obviously, both queries cannot be made at the exact same moment. So let's say that Thread-1 was queried first, followed by the query of Thread-2. The results are:Thread-1.....16 Thread-2.....2.49
4. The queries are NON-suspended actions performed on suspended Threads 1 & 2. Therefore, the results should be the same regardless of when the queries were actually made. Thus, the queries are actions that do not affect the results, once the threads have settled down into their suspended states. There will be many times when the above timing disparities will not be an issue...I may simply need to see the results at time (t) regardless of any synchronization issues. If I need better synchronization so that the outputs are synchronized at some value of an independent variable, then I can simply stop each thread independently on separate time-dependent bounds. Beyond that, why, in your understanding, would the queries affect the results? -
Sorry for the frustration showing. But in an attempt to understand what is going on, here is the way threads should behave the way I understand it. Let's say I have two threads that calculate the results of some equations:
Thread-1 produces 1........2....... 4.......8........16.......32 Thread-2 produces 1.5....1.837....2.49....3.929....7.789....21.737
1. All threads are suspended at time (t). Since Thread-1 is iterating faster than Thread-2, due to simpler equations, Thread-1 makes more progress than Thread-2, by time (t). 2. Since the exact moments that Threads 1 & 2 will be suspended will most likely occur asynchronously, this may add further uncertainty as to when Threads 1 & 2 will actually come to a halt. This could result in another complete iteration "slipping through" in either thread. But most likely, each thread will be suspended somewhere in the middle of an iteration. Nonetheless, the output values will not change until an iteration is completed. 3. At time (t + DELTAt), queries are made of the results from Threads 1 & 2. Obviously, both queries cannot be made at the exact same moment. So let's say that Thread-1 was queried first, followed by the query of Thread-2. The results are:Thread-1.....16 Thread-2.....2.49
4. The queries are NON-suspended actions performed on suspended Threads 1 & 2. Therefore, the results should be the same regardless of when the queries were actually made. Thus, the queries are actions that do not affect the results, once the threads have settled down into their suspended states. There will be many times when the above timing disparities will not be an issue...I may simply need to see the results at time (t) regardless of any synchronization issues. If I need better synchronization so that the outputs are synchronized at some value of an independent variable, then I can simply stop each thread independently on separate time-dependent bounds. Beyond that, why, in your understanding, would the queries affect the results?First, a little about threading... Threads are just units of work that are broken up to be run on a processor. There cannot be any more truly asynchronous threads running than there are physical processor cores. The system has a scheduler which operates in a time cycle, lets call this cycle length "N". In N time, it has to execute all the threads that are available to be run (threads in other states are not scheduled). Each thread is given a time slice, "Y" in which to execute before the processor context switches to another thread. Any unused time is given to the system process which is just a simple loop (processors always have to be doing something). Unless a thread yields (Thread.Yield or Thread.Sleep), it will process for its entire Y period. Processes that do this are using the most processor resources and you can watch the task manager increase in percent usage when this happens. So, getting back to your comments: 1) Suspending a thread is simply putting its state in the SleepWaitJoin. 2) The "exact" moment that the thread is (I believe) dependent on what the thread is currently doing. If the threads are in the scheduler but have not been run, then I think they are removed from the scheduler. If the thread is running then the scheduler has to wait until the time period expires or the thread yields to place it in the SleepWaitJoin state. So yes, another iteration can "slip" through while this process happens. 3) Queries happen at exactly the same moment according to the threads, this is because the thread executing the query is reading data in a thread that is suspended (one thread is running at a time). This doesn't mean however that you will get the results at the same time, again the thread could yield while reading data and you will get results at different thread times. 4) Again, the results may be different depending on how and when the scheduler interrupts the thread. Even your main thread is a thread, and its scheduled like all the rest of them. What you are really trying to do is synchronize data between threads, (Thread 1 to main thread and Thread 2 to main thread). You should not rely on when a thread suspends to do this, you need to implement your own synchronization. Luckily there are things like Mutex's, AutoResetEvent, etc that you can use cross-thread to make one thread wait on your main thread to say "go ahead, continue".
-
First, a little about threading... Threads are just units of work that are broken up to be run on a processor. There cannot be any more truly asynchronous threads running than there are physical processor cores. The system has a scheduler which operates in a time cycle, lets call this cycle length "N". In N time, it has to execute all the threads that are available to be run (threads in other states are not scheduled). Each thread is given a time slice, "Y" in which to execute before the processor context switches to another thread. Any unused time is given to the system process which is just a simple loop (processors always have to be doing something). Unless a thread yields (Thread.Yield or Thread.Sleep), it will process for its entire Y period. Processes that do this are using the most processor resources and you can watch the task manager increase in percent usage when this happens. So, getting back to your comments: 1) Suspending a thread is simply putting its state in the SleepWaitJoin. 2) The "exact" moment that the thread is (I believe) dependent on what the thread is currently doing. If the threads are in the scheduler but have not been run, then I think they are removed from the scheduler. If the thread is running then the scheduler has to wait until the time period expires or the thread yields to place it in the SleepWaitJoin state. So yes, another iteration can "slip" through while this process happens. 3) Queries happen at exactly the same moment according to the threads, this is because the thread executing the query is reading data in a thread that is suspended (one thread is running at a time). This doesn't mean however that you will get the results at the same time, again the thread could yield while reading data and you will get results at different thread times. 4) Again, the results may be different depending on how and when the scheduler interrupts the thread. Even your main thread is a thread, and its scheduled like all the rest of them. What you are really trying to do is synchronize data between threads, (Thread 1 to main thread and Thread 2 to main thread). You should not rely on when a thread suspends to do this, you need to implement your own synchronization. Luckily there are things like Mutex's, AutoResetEvent, etc that you can use cross-thread to make one thread wait on your main thread to say "go ahead, continue".
Ron and everyone, thank you for your replies. I think the last post is pretty much what I am saying in my hypothetical example that Ron responded to. But in going back over what everyone has said, I still don't see how, once a thread is suspended and queried, that the result should differ afterwards when that very result is then stored in a string variable. The thread is suspended and is not processing any more of its operations. "When you get the value of a property, the debugger executes the property Get code, so the thread isn't entirely stopped. As was already mentioned, the act of viewing an object changes it's state!" If the Schrodinger's Cat analogy is used, it means that when a suspended thread is queried, it for some reason then processes at least some more lines of code OTHER THAN the Get property, that could change that value. Get should not be able to allow its thread to process any other code, like any equations that were about to be executed but were halted. But even then, only one query has been made. When afterwards, that result is stored in a string, it has already been "captured" and is simply sitting there, being copied over into the string. Immediately after the query, shouldn't interaction with that thread already have been finished? The query has been made, which means a result has been pulled OUT of the thread. So the result is now isolated from that thread. The thread is no longer involved and can't somwhow reach out of itself to change that returned value. So the string copy should match the query result, exactly. If what you suggest is true (and maybe it is :) ), that is analogous to taking a digital picture of someone with a camera, and then when you copied that image over to your harddrive, it changed into a picture of someone else!
-
Ron and everyone, thank you for your replies. I think the last post is pretty much what I am saying in my hypothetical example that Ron responded to. But in going back over what everyone has said, I still don't see how, once a thread is suspended and queried, that the result should differ afterwards when that very result is then stored in a string variable. The thread is suspended and is not processing any more of its operations. "When you get the value of a property, the debugger executes the property Get code, so the thread isn't entirely stopped. As was already mentioned, the act of viewing an object changes it's state!" If the Schrodinger's Cat analogy is used, it means that when a suspended thread is queried, it for some reason then processes at least some more lines of code OTHER THAN the Get property, that could change that value. Get should not be able to allow its thread to process any other code, like any equations that were about to be executed but were halted. But even then, only one query has been made. When afterwards, that result is stored in a string, it has already been "captured" and is simply sitting there, being copied over into the string. Immediately after the query, shouldn't interaction with that thread already have been finished? The query has been made, which means a result has been pulled OUT of the thread. So the result is now isolated from that thread. The thread is no longer involved and can't somwhow reach out of itself to change that returned value. So the string copy should match the query result, exactly. If what you suggest is true (and maybe it is :) ), that is analogous to taking a digital picture of someone with a camera, and then when you copied that image over to your harddrive, it changed into a picture of someone else!
I'm not going to get into this any further because you're beating a dead horse. But, to add to the description that Ron just posted, in your description, you're ASSUMING that both of your background threads are running at the same time. This is NOT the case! Both threads, MAY be running, or one thread will run and the other won't be, or neither of them will be. Oh, and you're also assuming that threads will run in the order created. None of this is true. Threads can run in any order, for any amount of time, not necessarily the exact same size timeslice. Normally, the only time you ever look at ThreadState is when you're waiting for it to spin up or waiting for it to end. That's it. Any other use is not reliable as a synchronization method.
A guide to posting questions on CodeProject[^]
Dave Kreskowiak