3

According to the documentation, :

Because the Running state has a value of 0, it is not possible to perform a bit test to discover this state. Instead, the following test (in pseudo-code) can be used:

if ((state & (Unstarted | Stopped)) == 0)   // implies Running

Threads are often in more than one state at any given time.

and api

The Thread.ThreadState property of a thread provides the current state of a thread. Applications must use a bitmask to determine whether a thread is running. Since the value for Running is zero (0), test whether a thread is running by using C# code such as (myThread.ThreadState & (ThreadState.Stopped | ThreadState.Unstarted)) == 0 or Visual Basic code such as (myThread.ThreadState And (ThreadState.Stopped Or ThreadState.Unstarted)) = 0.

Searching through SO (1,2,3) I only find why ThreadState should not be used for flow control since the state checked could immediately change. For cases when you check it for debugging why would you use the bitmask above as opposed to just myThread.ThreadState==0?

user5389726598465
  • 1,418
  • 2
  • 14
  • 25
  • Because of AbortRequested or SuspendRequested or ...? – Sir Rufo Feb 03 '18 at 08:18
  • @SirRufo I don't follow. Then it wouldn't be in Running state but why is 0 bitwise &'ed with the initial or final states? – user5389726598465 Feb 03 '18 at 08:21
  • A **running** thread can also have the state **AbortRequested** (should abort ASAP) or maybe **Background**. Now ThreadState is != 0 although it is running – Sir Rufo Feb 03 '18 at 08:25
  • Since `ThreadState` is marked with the `[FlagsAttribute]`, can you even do `myThread.ThreadState == 0`? – Tim Feb 03 '18 at 08:27
  • @SirRufo Nobody give up on me. Still confused. The RunningState is the only one that is mutually exclusive of any other state because of its zero value, not because of possible status of the thread. But it's also not in the running state when it's in abortRequested or anything else. Now why would you & 0 with the initial and final values? – user5389726598465 Feb 03 '18 at 08:31
  • @SirRufo The given line though is not to include the states that are running but not zero. – user5389726598465 Feb 03 '18 at 08:35
  • 1
    To answer the main question: Because the thread is running when it is NOT Unstarted and NOT Stopped. It is a definition from the class designer – Sir Rufo Feb 03 '18 at 08:44
  • @SirRufo ok, I understand now. It *is* checking for isAlive() after all. – user5389726598465 Feb 03 '18 at 08:46
  • @SirRufo +1 on a random question of yours. System wouldn't let me do 2. :) – user5389726598465 Feb 03 '18 at 08:50

1 Answers1

2

The enum / bit mask here is to restrict you to checking two bits. There are other bits in the status that do not tell you whether it is running or not - so them being set (1) or not set (0) doesn't change whether you should consider it running. For example, having the WaitSleepJoin bit set, or the SuspendRequested bit set - doesn't change that it is "running", for most useful purposes.

So: the state & (Unstarted | Stopped) says "just looking at these two bits, and ignoring the rest"...

The full set of documented flags are:

[Serializable, Flags, ComVisible(true)]
public enum ThreadState
{
    Aborted = 256,
    AbortRequested = 128,
    Background = 4,
    Running = 0,
    Stopped = 16,
    StopRequested = 1,
    Suspended = 64,
    SuspendRequested = 2,
    Unstarted = 8,
    WaitSleepJoin = 32
}

I say "documented", because enums aren't enforced - the value could theoretically come back as 2050 or -6 - with whatever bit flags are set for those.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • and it's confusing because nonzero is false so (unstarted | stopped) means NOT unstarted or stopped – user5389726598465 Feb 03 '18 at 10:08
  • @user5389726598465 maybe, but in other ways : checking for `0` is nice - most of the flags are a *deviation from the normal state* - 0 being "all normal". Arguably the background flag being set doesn't change "normal" – Marc Gravell Feb 03 '18 at 10:12