正确使用Win32线程

时间:2015-10-03 07:40:23

标签: c++ multithreading

我刚学习Win32编程并且有一个关于线程的问题。假设我有下面的例子,我想知道在for循环中调用的PrintStuff()函数是在创建的新线程上运行还是在主线程上运行?谢谢。

    HANDLE hThrd;
    DWORD WINAPI PrintStuff() {
        OutputDebugString("printing stuff");
        return 0;
    }
    int WINAPI WinMain(...) {
        ...
        hThrd = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PrintStuff, NULL, CREATE_SUSPENDED, &id)
        int i;
        for (i = 0; i < 5; i++) {
            PrintStuff();
        }
        ...
    }

4 个答案:

答案 0 :(得分:2)

你似乎认为CreateThread不知何故&#34;标记&#34;一个要在另一个线程中运行的函数,这样每次调用它都会在另一个线程中运行。它不是那样的。 CreateThread,顾名思义,只创建一个新的线程,其入口点是您指定的函数。调用之后的所有指令仍然在与之前相同的线程中运行,而您指定的函数将在调用CreateThread后的一段时间内在一个单独的线程中调用一次。

顺便说一句,如果您打算在新创建的线程上使用标准库中的任何函数,则不应直接使用CreateThread,而是使用_beginthread

我现在看到你正在指定CREATE_SUSPENDED标志;因此,除非您在其上调用ResumeThread,否则新线程将永远不会运行。

答案 1 :(得分:1)

有多种方法可以确定哪个线程正在运行该函数。

1。获取当前线程ID

GetCurrentThreadId()可与Windows API一起使用。

C ++中还有很多其他方法。 C ++标准库还在#include <thread>中提供std::this_thread::get_id(),可用于以独立于平台的方式获取ID进行比较。

使用线程ID,您只需检查WinMain开头的线程ID,并将主线程的ID存储在全局变量中,您可以在PrintStuff中使用该变量。

请注意,标准库get_id()返回的ID集与GetCurrentThreadId()不同,因此您需要选择一个。

2。使用线程局部变量。

在使用Visual Studio的Windows平台上,您可以使用__declspec(thread)。如果您有C ++ 14(Visual Studio 2015提供),则可以使用thread_local

使用线程局部变量,如果主线程正在运行该函数,则可以轻松计算出来。

__declspec(thread) bool isMainThread = false;
HANDLE hThrd;
DWORD WINAPI PrintStuff() {
    OutputDebugString("printing stuff");
    // check isMainThread here
    return 0;
}
int WINAPI WinMain(...) {
    isMainThread = true;
    ...
    hThrd = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PrintStuff, NULL, CREATE_SUSPENDED, &id)
    int i;
    for (i = 0; i < 5; i++) {
        PrintStuff();
    }
    ...
}

线程局部变量可用于存储线程名称,而不仅仅是打印一个并不总是易于理解的线程ID。

3。将参数传递给函数,或使用包装函数

如果您只想以不同方式打印,可以在创建新线程时使用包装函数,并使用此函数将参数传递给PrintStuff函数。如果您不想将参数传递给PrintStuff来执行不同的操作,您还可以使用包装函数来设置线程局部变量。这是您可以为线程命名的地方。

答案 2 :(得分:0)

你可以打印threadId来查看使用了什么线程。

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

如果要检查它是否在主线程中打印,可以获取上面使用的主要threadId并将其与PrintStuff中的threadId进行比较。

答案 3 :(得分:0)

使用函数中的GetCurrentThreadId()来了解当前正在执行它的线程。

DWORD WINAPI PrintStuff() {
    DWORD idThread = GetCurrentThreadId();
    printf("Thread ID: %i.\n", idThread);
}