How can I check the status of one thread from another in thread safe mode?

Background:

While debugging my application, I came across this function

boolean IsThreadGood(Thread t)
{
    return t.IsAlive && t.ThreadState == ThreadState.Running || t.ThreadState == ThreadState.WaitSleepJoin;
}

      

I thought this was a bug, since the logical comparisons occurring in the return statement are not atomic, and so I thought that Thread t could change states while the expression was being executed. To test this idea, I changed the code to the following code to accommodate breakpoints:

bool IsThreadGood(Thread t)
{
    if (t.IsAlive)
    {
        if (t.ThreadState == ThreadState.Running)
        {
            return true;
        }
        if (t.ThreadState == ThreadState.WaitSleepJoin)
        {
           return true;
        }
    }
    return false;
}

      

I put a breakpoint on the inner if statements and pretty quickly saw what I suspected. When the code reached the first breakpoint, Thread t had a ThreadState from WaitSleepJoin, and when I stepped over the code to the next one, if Thread t statement had toggle states and had ThreadState Running, so both tests failed and return false from the method when it should return true.

My question is:

How can I do if I can check the state of a thread from another thread with a safe thread?

My ideas and what I researched:

  • If I could make the assertion atomic it would work. I googled some things like "how to make an atom assertion in C #" and got a lot of results with locks - not what I want because, as far as I understand, locks don't make the code atomic.

  • If I could suspend Thread t from the thread executing this method, then I could safely check its state. What I found here is the deprecated Suspend and Resume functions. Microsoft strongly recommends against using them.

  • Changing Thread t somehow implements synchronization. Not an option. The code is reusable code that is used differently by different clients, and Thread t is the client code. It will not be possible to change all clients.

I am not a multithreading guru, so if any of my assumptions are wrong or my understanding of multithreading is wrong, feel free to point it out.

+3


source to share


3 answers


I am sure that a thread whose state either Running

or WaitSleepJoin

cannot be lifeless. So you can just get the state (which is an atomic operation) and then check those two values:

boolean IsThreadGood(Thread t)
{
    ThreadState state = t.ThreadState;
    return state == ThreadState.Running || state == ThreadState.WaitSleepJoin;
}

      

Note that the documentation explicitly states that you should only use thread state for debugging purposes and not for synchronization:



The thread state is of interest only for debugging scenarios. Your code should never use thread state to synchronize thread actions.

Since you are interested in atomic operation, I doubt if you want this for debugging purposes (otherwise you wouldn't have to worry about it being super accurate). Therefore, you should probably think about how to solve your actual problem in a different way.

+3


source


It will never work. The thread could be in the last instruction and your check will miss the closest and guaranteed exit. The thread needs to cooperate with you. You need to sync at a higher level. I can't suggest it because I don't know what the app does. Post a new question with details and code.

Note that it t.IsAlive && t.ThreadState == ThreadState.Running || t.ThreadState == ThreadState.WaitSleepJoin

skips the parentheses around the operator ||

. It doesn't matter, because this code should be thrown away.

What is supposed state == ThreadState.WaitSleepJoin

? This state can be false because many libraries can enter this state. It all seems bogus.



As a workaround, you can implement a watchdog stream:

while (true)
 DetectExit();
 Sleep(100);

      

+1


source


The method Thread.Join(int millisecondsTimeout)

can be used to safely test thread termination. It returns true when the thread is no longer active.

 // 0 == don't wait.
 if (thread.Join(0))
 {
    // remove thread from the list
 }

      

For obvious reasons, it should be called from another thread.

0


source







All Articles