2 votes

Traduction de boost::thread->native_handle() en XP ThreadId

J'ai réussi à faire sortir le ThreadId de Windows de la fonction native_handle() d'un boost::thread en utilisant GetThreadId(HANDLE) . Malheureusement, cet appel n'est pas disponible sous Windows XP et après avoir cherché un peu partout, j'ai trouvé la solution pour offrir un support de secours pour XP en traversant tous les threads par l'intermédiaire de Thread32First() y Thread32Next() les fonctions de l'interface WINAPI.

Cela fonctionne en quelque sorte, mais mon problème est que je ne suis actuellement capable d'identifier que les fils de mon processus... Je ne sais pas comment faire correspondre le native_handle() / POIGNÉE d'un côté, avec les THREADENTRY32 de la traversée de la boucle.

THREADENTRY32 te32;
//...
do { 
    if( te32.th32OwnerProcessID == GetCurrentProcessId() ) {
        DWORD threadId = te32.th32ThreadID;
        printf( "\n     THREAD ID      = 0x%08X", te32.th32ThreadID ); 
    }
} while( Thread32Next(hThreadSnap, &te32 ) );

Quelqu'un peut-il m'aider ? Comment convertir un boost::thread->native_handle() en ThreadId sous WindowsXP ?

Merci beaucoup !

2voto

Remy Lebeau Points 130112

Passez chaque ID de fil dans la boucle à OpenThread() jusqu'à ce que vous trouviez une correspondance HANDLE . Par exemple :

HANDLE hBoostThread = ...; // from boost::thread->native_handle()
DWORD dwBoostThreadID = 0;

THREADENTRY32 te32;
//...
do
{ 
    if( te32.th32OwnerProcessID == GetCurrentProcessId() )
    {
        HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, te32.th32ThreadID);
        if (hThread != NULL)
        {
            if (hThread == hBoostThread)
            {
                CloseHandle(hThread);
                dwBoostThreadID = te32.th32ThreadID; 
                break;
            }
            CloseHandle(hThread);
        }
    }
}
while( Thread32Next(hThreadSnap, &te32 ) );

Pour faire bonne mesure, vous pouvez inclure cette fonction dans une fonction que vous pouvez appeler chaque fois que vous le souhaitez. GetThreadId() n'est pas disponible de manière native afin que votre code n'ait pas besoin de connaître la différence, par exemple :

DWORD WINAPI MyGetThreadId(HANDLE Thread)
{
    THREADENTRY32 te32;

    HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
    if (hThreadSnap == INVALID_HANDLE_VALUE)
        return 0;

    if (Thread32First(hThreadSnap, &te32))
    {
        do
        { 
            HANDLE hOpenThread = OpenThread(THREAD_ALL_ACCESS, FALSE, te32.th32ThreadID);
            if (hOpenThread != NULL)
            {
                if (hOpenThread == Thread)
                {
                    CloseHandle(hOpenThread);
                    CloseHandle(hThreadSnap);
                    return te32.th32ThreadID; 
                }

                CloseHandle(hOpenThread);
            }
        }
        while( Thread32Next(hThreadSnap, &te32 ) );
    }

    CloseHandle(hThreadSnap);
    return 0;
}

typedef DWORD (WINAPI *LPFN_GTID)(HANDLE);

LPFN_GTID lpGetThreadId = (LPFN_GTID) GetProcAddress(GetModuleHandle("kernel32"), "GetThreadId");
if (!lpGetThreadId)
    lpGetThreadId = &MyGetThreadId;

DWORD dwThreadID = lpGetThreadId((HANDLE) boost::thread->native_handle());

Cela dit, il est préférable d'interroger directement le fil cible pour connaître son propre identifiant, au lieu d'essayer de le rechercher manuellement :

typedef long (WINAPI *LPFN_NTQIT)(HANDLE thread, int infoclass, void *buf, long size, long *used);

typedef struct _THREAD_BASIC_INFORMATION
{
    ULONG ExitStatus;
    void* TebBaseAddress;
    ULONG UniqueProcessId;
    ULONG UniqueThreadId;
    ULONG AffinityMask;
    ULONG BasePriority;
    ULONG DiffProcessPriority;
} THREAD_BASIC_INFORMATION;

DWORD WINAPI MyGetThreadId(HANDLE Thread)
{
    DWORD dwThreadId = 0;

    HMODULE hLib = LoadLibrary("ntdll.dll");
    if (hLib != NULL)
    {
        LPFN_NTQIT lpNtQueryInformationThread = (LPFN_NTQIT) GetProcAddress(hLib, "NtQueryInformationThread");

        if (lpNtQueryInformationThread != NULL)
        {
            THREAD_BASIC_INFORMATION tbi = {0};
            ULONG used = 0;

            if (lpNtQueryInformationThread(Thread, 0, &tbi, sizeof(tbi), &used) == 0)
                dwThreadId = tbi.UniqueThreadId;
        }

        FreeLibrary(hLib);
    }

    return dwThreadId;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X