我刚学习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();
}
...
}
答案 0 :(得分:2)
你似乎认为CreateThread
不知何故&#34;标记&#34;一个要在另一个线程中运行的函数,这样每次调用它都会在另一个线程中运行。它不是那样的。 CreateThread
,顾名思义,只创建一个新的线程,其入口点是您指定的函数。调用之后的所有指令仍然在与之前相同的线程中运行,而您指定的函数将在调用CreateThread
后的一段时间内在一个单独的线程中调用一次。
顺便说一句,如果您打算在新创建的线程上使用标准库中的任何函数,则不应直接使用CreateThread
,而是使用_beginthread
。
我现在看到你正在指定CREATE_SUSPENDED
标志;因此,除非您在其上调用ResumeThread
,否则新线程将永远不会运行。
答案 1 :(得分:1)
有多种方法可以确定哪个线程正在运行该函数。
GetCurrentThreadId()
可与Windows API一起使用。
C ++中还有很多其他方法。 C ++标准库还在#include <thread>
中提供std::this_thread::get_id()
,可用于以独立于平台的方式获取ID进行比较。
使用线程ID,您只需检查WinMain开头的线程ID,并将主线程的ID存储在全局变量中,您可以在PrintStuff中使用该变量。
请注意,标准库get_id()返回的ID集与GetCurrentThreadId()不同,因此您需要选择一个。
在使用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。
如果您只想以不同方式打印,可以在创建新线程时使用包装函数,并使用此函数将参数传递给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);
}