当我尝试使用CreateThread
函数时,我有一个奇怪的错误。这是我的代码:
HANDLE threads[3]; //threads[0] is printer, threads[1] is receiver, [2] is serverconn
DWORD printer_id, receiver_id, serverconn_id;
if(
((threads [0] = CreateThread(NULL, 0, printer_thread, (LPVOID) thread_args, 0, &printer_id)) == NULL) ||
((recv_thread = threads [1] = CreateThread(NULL, 0, receiver_thread, (LPVOID) thread_args, 0, &receiver_id)) == NULL) ||
((threads [2] = CreateThread(NULL, 0, serverconn_thread, (LPVOID) thread_args, 0, &serverconn_id)) == NULL)
)
{
IO_print_line("Initialization error");
return FALSE;
}
printer_thread
,receiver_thread
和serverconn_thread
是这样定义的函数:
int serverconn_thread(LPVOID args);
Visual Studio编译器给出了这个错误:
Error C2440 'function': cannot convert from 'int (__cdecl *)(LPVOID)' to 'LPTHREAD_START_ROUTINE'
我真的不明白,因为我认为我已经完成what the official documentation suggests。
不,将线程函数的返回类型更改为DWORD
并没有解决任何问题,错误只会更改为:
Error C2440 'function': cannot convert from 'DWORD (__cdecl *)(LPVOID)' to 'LPTHREAD_START_ROUTINE'
奇怪的是,如果我这样改变它:
if(
((threads [0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &printer_thread, (LPVOID) thread_args, 0, &printer_id)) == NULL) ||
((recv_thread = threads [1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &receiver_thread, (LPVOID) thread_args, 0, &receiver_id)) == NULL) ||
((threads [2] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &serverconn_thread, (LPVOID) thread_args, 0, &serverconn_id)) == NULL)
)
使用强制转换,编译器可以,但我不认为以这种方式强制执行它是个好主意。我该如何解决这个问题?
答案 0 :(得分:1)
在声明线程功能时,您没有关注official documentation。
您的原始声明使用int
作为返回值,__cdecl
(隐式)作为调用约定。当您将返回值更改为DWORD
时,您没有更改调用约定。
但是,documentation清楚地显示了正确的声明:
DWORD WINAPI ThreadProc( _In_ LPVOID lpParameter );
DWORD
是unsigned long
,WINAPI
是一个映射到__stdcall
调用约定的宏(请参阅Windows Data Types)。
因此,您的函数的正确声明将是:
unsigned long __stdcall printer_thread(void *args);
unsigned long __stdcall receiver_thread(void *args);
unsigned long __stdcall serverconn_thread(void *args);
但是,由于CreateThread()
将LPTHREAD_START_ROUTINE
作为输入,声明为DWORD (WINAPI*)(LPVOID)
(请参阅winbase.h
中的实际声明),因此您应声明要匹配的函数:
DWORD WINAPI printer_thread(LPVOID args);
DWORD WINAPI receiver_thread(LPVOID args);
DWORD WINAPI serverconn_thread(LPVOID args);