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

时间:2016-02-26 05:05:46

标签: c++ windows multithreading winapi

使用下面的程序终止每个线程后,我需要每次都用ids打印剩余的线程,我正在使用GetExitCodeThread函数,但是它返回了一些垃圾值。我可能做错了什么?还有,怎么样在获得exitCode正确后打印剩余的线程?

#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 %d\n", 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= %d\n", 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;
}

2 个答案:

答案 0 :(得分: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 detected\n", 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 threads\n", 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("Created\n");
            ++numThreadsRunning;
        }
        else
            printf("Not Created!\n");
    }

    printf("Threads running: %d\n", 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 Terminate\n", 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: %u\n", id, exitCode);

            --numThreadsRunning;
            printf ("Threads still running: %d\n", numThreadsRunning);
        }
        else
            printf ("Thread %d is not running\n", id);
    }

    if (numThreadsRunning > 0)
    {
        printf ("Signaling remaining Threads to Terminate\n");

        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 Terminated\n");
    }

    return 0;
}

答案 1 :(得分: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 );
}