Solved

How to determine termination status of a thread.

Posted on 1998-10-11
11
398 Views
Last Modified: 2013-11-20
Hi

I will probably figure this out during the time period it takes someone to respond, but this weird.

So here is the setup.  I have an array of CWinThread objects.  Some of these are NULL, indicating they are not currently in use.  Others are assigned a thread that is running, but the thread will probably terminate after about, ohhhhh, 10 seconds.

To prevent the program from exiting while a thread is running, I am using this:

  int i;
  DWORD exitcode;

  for (int j = 0; j < 100; j++)
  { for (i = 0; i < 16; i++)
    { if (m_Threads[i] != NULL)
      { GetExitCodeThread (m_Threads[i]->m_hThread, &exitcode);

        if (exitcode == STILL_ACTIVE)
        { break; }
        MessageBeep (0xffffffff);
      }
    }

    if (exitcode != STILL_ACTIVE)
    { break; }

    Sleep (100); // Wait until all threads have terminated.
  }

The intent of the code is to wait until the program has exited, but the loops will never terminate early, they always go through the whole thing.

What could be causing this?
0
Comment
Question by:helpmealot
  • 5
  • 3
  • 3
11 Comments
 
LVL 23

Expert Comment

by:chensu
ID: 1323185
You should use the Wait functions (e.g. WaitForSingleObject) on the thread handles to detect if the threads has terminated. Your method wastes a lot of CPU time. As a result, the threads have less time to execute.
0
 
LVL 86

Accepted Solution

by:
jkr earned 70 total points
ID: 1323186
'GetExitCodeThread()' is not very reliable for this task - i prefer calling 'WaitForSingleObject()' using a small timeout - the object's state is signaled when it terminates, so 'WAIT_TIMEOUT' guarantees that it's still running...

0
 

Author Comment

by:helpmealot
ID: 1323187
Okay, it sounds like this function WaitForSingleObject is what I am looking for.  However, I am not sure how to use it.  This is my first project using threads, so I am very unclear as to what I do with it.  Can you please elaborate?  I will divide the points between you if you both give good explanations :)
0
 
LVL 23

Expert Comment

by:chensu
ID: 1323188
A thread object's state is signaled when the thread terminates.

if (::WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0)
{
    // the thread has terminated
}

The WaitForSingleObject function returns when one of the following occurs:

1. The specified object is in the signaled state.
2. The time-out interval elapses.
0
 
LVL 86

Expert Comment

by:jkr
ID: 1323189
Well, IMHO there's nothing to add to chensu's explanation, the only difference is that i'd use

if (::WaitForSingleObject(hThread, 1) == WAIT_TIMEOUT)
{
    // the thread is still running...
}

0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 

Author Comment

by:helpmealot
ID: 1323190
Okay I see, that seems to make sense now.  I am going to split the points between you because I was able to incorporate chensu's suggestion for the exiting part of the program and jkr's solution for the parts of the program where a new thread would start.  First though, I have one other question (coming):
0
 

Author Comment

by:helpmealot
ID: 1323191
You see, to keep track of the threads running in the program, I have created an array of CWinThreads.  When a new thread is created, this code is executed:

  { CWinThread *nThread;
    // ...
    // nthread is assigned a valid CWinThread object.

    for (int i = 0; i < 16; i++) // 16 cause I have 16 CWinThreads in the array.
    { if (m_Threads[i] != NULL)  // All CWinThreads are initialized to 0 when the program starts.
      { if (::WaitForSingleObject (m_Threads[i], 1) != WAIT_TIMEOUT) // thread is dead.
        { m_Threads[i] = nThread;
          break;
        }
      }
      else // or object hasn't been used yet.
      { m_Threads[i] = nThread;
        break;
      }
    }
  }

Is that code good?  Are there any problems with it?  Any potential improvements?  That sort of thing.

One more other question along these same lines coming:
0
 

Author Comment

by:helpmealot
ID: 1323192
When my program exits, I want it to wait for all threads to terminate.  Is this right:

  for (i = 0; i < 16; i++)
  { if (m_Threads[i] != NULL)
    { ::WaitForSingleObject (m_Threads[i]->m_hThread, INFINITE); }
  }

It seems to work, but I have had experience where something seems to work but it turns out it doesn't.  That is why I am asking :-)

Does that make sense?  Any other suggestions?

I will give each of you 75 points and an A since you have both helped me a great deal!

Thanks!
0
 
LVL 23

Expert Comment

by:chensu
ID: 1323193
1. Regarding the code when a new thread is created, I think you can use
if (::WaitForSingleObject(m_Threads[i]->m_hThread, 0) == WAIT_OBJECT_0)
instead of
if (::WaitForSingleObject(m_Threads[i]->m_hThread, 1) != WAIT_TIMEOUT)

2. Regarding the code when the program exits, I think you may use a certain time instead of INFINITE in case there is something wrong. MsgWaitForMultipleObjects or MsgWaitForMultipleObjectsEx are your options too.

In addition, it is more reliable to handle the errors returned by WaitForSingleObject.
0
 
LVL 86

Expert Comment

by:jkr
ID: 1323194
If you already have an array of thread handles (e.g. you know the number) 'WaitForMultipleObjects()' will do the job well (and is more reliable & flexible than using a loop). 'MsgWaitForMultipleObjects()' also handles messages, but if you don't need to take care about messages, it provides no advantage...
0
 

Author Comment

by:helpmealot
ID: 1323195
Okay, that has cleared up everything for me.  chensu - I am going to post a question the MFC area "addressed" to you so you can get your 75 points too.
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Introduction: The undo support, implementing a stack. Continuing from the eigth article about sudoku.   We need a mechanism to keep track of the digits entered so as to implement an undo mechanism.  This should be a ‘Last In First Out’ collec…
Have you tried to learn about Unicode, UTF-8, and multibyte text encoding and all the articles are just too "academic" or too technical? This article aims to make the whole topic easy for just about anyone to understand.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now