如何在Windows线程中终止线程后获取剩余线程数?C++



使用以下程序终止每个线程后,我需要每次打印带有 id 的剩余线程,为此我使用 GetExitCodeThread 函数,但它返回了一些垃圾值。我可能做错了什么?另外,在退出代码正确后如何打印剩余的线程?

#define NUM_THREADS 10
#include <windows.h>
#include <stdio.h>
#include <process.h>
typedef struct
{
int Id;
HANDLE hTerminate;
} ThreadArgs;
unsigned _stdcall ThreadFunc( void *pArgs )
{
LPDWORD exitCode;
HANDLE hTerminate = ((ThreadArgs *)pArgs)->hTerminate;
int id = ((ThreadArgs *)pArgs)->Id;
// run until we are told to terminate while (1)
while(1)
{
    // Check to see if we should terminate
    if (WaitForSingleObject(hTerminate, 0) == WAIT_OBJECT_0)
    {
        // Terminate Thread - we call ResetEvent to
        // return the terminate thread to its non-
        // signaled state, then exit the while() loop
        printf ("Terminating Thread %dn", id);
        GetExitCodeThread(hTerminate,exitCode);
        printf("%d",exitCode);
        ResetEvent(hTerminate);
        break;
    }
// we can do our work now ...
// simulate the case that it takes
// to do the work the thread has to do
Sleep(1000);
}
_endthreadex(0);
return 0;
}
int main(int argc, char* argv[])
{
int i=0;
unsigned int threadID[NUM_THREADS];
HANDLE hThread[NUM_THREADS];
ThreadArgs threadArgs[NUM_THREADS];
// Create 10 threads
printf("Total number of threads= %dn", NUM_THREADS);
for (i = 0; i < NUM_THREADS;i++)
{
    printf("Thread number %d n",i);
}
for (int i = 0; i<NUM_THREADS;i++)
{
    threadArgs[i].Id = i;
    threadArgs[i].hTerminate = CreateEvent(NULL,TRUE,FALSE,NULL);
    hThread[i] = (HANDLE)_beginthreadex(NULL,0,&ThreadFunc,&threadArgs[i],       0, &threadID[i]);
}
printf("To kill a thread (gracefully), press 0-9, "" then <Enter>. n");
printf("Press any other key to exit.n");

while (1)
{
    int c = getc(stdin);
    if (c == 'n') 
        continue;
    if (c < '0' || c > '9') 
        break;
    SetEvent(threadArgs[c -'0'].hTerminate);
}
return 0;
}

GetExitCodeThread()期望对线程对象进行HANDLE,但您却将其HANDLE传递给事件对象。 您还将向其传递一个未初始化的指针,以将退出代码写入其中。 因此,GetExitCodeThread()将失败并显示您忽略的错误,并且不会为退出代码分配任何有意义的值。

这并不重要,因为GetExitCodeThread()仍在运行的线程内调用是没有用的,它会将退出代码设置为 STILL_ACTIVE . 您应该在与要终止的线程不同的线程中调用GetExitCodeThread()

尝试更多类似的东西:

#include <windows.h>
#include <stdio.h>
#include <process.h>
#define MAX_THREADS 10
typedef struct
{
    int Id;
    DWORD dwThreadId;
    HANDLE hThread;
    HANDLE hTerminate;
} ThreadArgs;
unsigned __stdcall ThreadFunc( void *arg )
{
    ThreadArgs *pArgs = (ThreadArgs *) arg;
    // run until we are told to terminate while (1)
    while(1)
    {
        // Check to see if we should terminate
        if (WaitForSingleObject(pArgs->hTerminate, 0) == WAIT_OBJECT_0)
        {
            // Terminate Thread - exit the while() loop
            printf ("Thread %d terminate signal detectedn", pArgs->Id);
            break;
        }
        // we can do our work now ...
        // simulate the case that it takes
        // to do the work the thread has to do
        Sleep(1000);
    }
    return 0;
}
int main(int argc, char* argv[])
{
    int i;
    ThreadArgs threadArgs[MAX_THREADS];
    int numThreadsRunning = 0;
    memset(&ThreadArgs, 0, sizeof(ThreadArgs));
    // Create 10 threads
    printf("Creating %d threadsn", MAX_THREADS);
    for (i = 0; i < MAX_THREADS; ++i)
    {
        printf("Thread number %d: ", i);
        threadArgs[i].Id = i;
        threadArgs[i].hTerminate = CreateEvent(NULL, TRUE, FALSE, NULL);
        threadArgs[i].hThread = (HANDLE) _beginthreadex(NULL, 0, &ThreadFunc, &threadArgs[i], 0, &threadArgs[i].dwThreadId);
        if (threadArgs[i].hThread != NULL)
        {
            printf("Createdn");
            ++numThreadsRunning;
        }
        else
            printf("Not Created!n");
    }
    printf("Threads running: %dn", numThreadsRunning);
    printf("To kill a thread (gracefully), press 0-%d, then <Enter>.n", MAX_THREADS-1);
    printf("Press any other key to exit.n");
    while (1)
    {
        int c = getc(stdin);
        if (c == 'n') 
            continue;
        if ((c < '0') || (c > '9'))
            break;
        int id = c - '0';
        if (threadArgs[id].hThread != NULL)
        {
            printf ("Signaling Thread %d to Terminaten", id);
            SetEvent(threadArgs[id].hTerminate);
            WaitForSingleObject(threadArgs[id].hThread, INFINITE);
            DWORD exitCode = 0;
            GetExitCodeThread(threadArgs[id].hThread, &exitCode);
            CloseHandle(threadArgs[id].hThread);
            threadArgs[id].hThread = NULL;
            printf ("Thread %d Terminated. Exit Code: %un", id, exitCode);
            --numThreadsRunning;
            printf ("Threads still running: %dn", numThreadsRunning);
        }
        else
            printf ("Thread %d is not runningn", id);
    }
    if (numThreadsRunning > 0)
    {
        printf ("Signaling remaining Threads to Terminaten");
        HANDLE hThreads[MAX_THREADS];
        DWORD numThreads = 0;
        for (i = 0; i < MAX_THREADS; ++i)
        {
            if (threadArgs[i].hThread != NULL)
            {
                hThreads[numThreads] = threadArgs[i].hThread;
                ++numThreads;
                SetEvent(threadArgs[i].hTerminate);
            }
        }
        WaitForMultipleObjects(numThreads, hThreads, TRUE, INFINITE);
        for (i = 0; i < MAX_THREADS; ++i)
        {
            if (hThreads[i].hThread)
                CloseHandle(hThreads[i].hThread);
            if (hThreads[i].hTerminate)
                CloseHandle(hThreads[i].hTerminate);
        }
        printf ("Threads Terminatedn");
    }
    return 0;
}

看看这篇 msdn 文章:

遍历线程列表

https://msdn.microsoft.com/en-us/library/windows/desktop/ms686852(v=vs.85).aspx

有关于如何列出进程线程的示例代码。

~剪 断

#include <windows.h>
#include <tlhelp32.h>
#include <tchar.h>
//  Forward declarations:
BOOL ListProcessThreads( DWORD dwOwnerPID );
void printError( TCHAR* msg );
int main( void )
{
  ListProcessThreads(GetCurrentProcessId() );
  return 0;
}
BOOL ListProcessThreads( DWORD dwOwnerPID ) 
{ 
  HANDLE hThreadSnap = INVALID_HANDLE_VALUE; 
  THREADENTRY32 te32; 
  // Take a snapshot of all running threads  
  hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 ); 
  if( hThreadSnap == INVALID_HANDLE_VALUE ) 
    return( FALSE ); 
  // Fill in the size of the structure before using it. 
  te32.dwSize = sizeof(THREADENTRY32 ); 
  // Retrieve information about the first thread,
  // and exit if unsuccessful
  if( !Thread32First( hThreadSnap, &te32 ) ) 
  {
    printError( TEXT("Thread32First") );  // Show cause of failure
    CloseHandle( hThreadSnap );     // Must clean up the snapshot object!
    return( FALSE );
  }
  // Now walk the thread list of the system,
  // and display information about each thread
  // associated with the specified process
  do 
  { 
    if( te32.th32OwnerProcessID == dwOwnerPID )
    {
      _tprintf( TEXT("n     THREAD ID      = 0x%08X"), te32.th32ThreadID ); 
      _tprintf( TEXT("n     base priority  = %d"), te32.tpBasePri ); 
      _tprintf( TEXT("n     delta priority = %d"), te32.tpDeltaPri ); 
    }
  } while( Thread32Next(hThreadSnap, &te32 ) );
  _tprintf( TEXT("n"));
//  Don't forget to clean up the snapshot object.
  CloseHandle( hThreadSnap );
  return( TRUE );
}
void printError( TCHAR* msg )
{
  DWORD eNum;
  TCHAR sysMsg[256];
  TCHAR* p;
  eNum = GetLastError( );
  FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
         NULL, eNum,
         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
         sysMsg, 256, NULL );
  // Trim the end of the line and terminate it with a null
  p = sysMsg;
  while( ( *p > 31 ) || ( *p == 9 ) )
    ++p;
  do { *p-- = 0; } while( ( p >= sysMsg ) &&
                          ( ( *p == '.' ) || ( *p < 33 ) ) );
  // Display the message
  _tprintf( TEXT("n  WARNING: %s failed with error %d (%s)"), msg, eNum, sysMsg );
}

最新更新