【问题标题】:How to get the number of remaining threads after terminating a thread in windows thread? c++终止windows线程中的线程后如何获取剩余线程数? C++
【发布时间】:2016-06-09 04:57:22
【问题描述】:

使用下面的程序终止每个线程后,我每次都需要打印带有 id 的剩余线程,为此我使用 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;
}

【问题讨论】:

    标签: c++ windows multithreading winapi


    【解决方案1】:

    看看这篇 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 );
    }
    

    【讨论】:

      【解决方案2】:

      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;
      }
      

      【讨论】:

        猜你喜欢
        • 2015-10-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-22
        • 1970-01-01
        • 1970-01-01
        • 2019-06-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多