我认为我正在陷入僵局,一直在寻找解决方案。有什么建议? 我想要做的是:ater startGame按钮单击,创建线程,发送请求到服务器,然后得到答案,在答案后线程必须发送消息初始化游戏窗口到主过程...
属于WinMain的Message Proc:
LRESULT CALLBACK WndProc(HWND myWindow, UINT messg, WPARAM wParam, LPARAM lParam)
{
switch (messg) {
case WM_STARTGAME:
DestroyWindow(hStartGameButton);
DestroyWindow(hHistoryButton);
InitGameWindow(myWindow);
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDC_STARTGAME_BUTTON:
{
parametros param;
param.myWindow = myWindow;
start_game = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadStartGame, (LPVOID)&myWindow, 0, NULL);
}
}
}
这就是主题:
DWORD WINAPI ThreadStartGame(LPVOID param){
HWND w = (HWND)param;
DWORD n;
BOOL ret;
mensagem resposta;
mensagem msg;
msg.tipo = COMECAR_JOGO;
msg.verifica = true;
if (!WriteFile(hPipe, &msg, (DWORD)sizeof(mensagem), &n, NULL)) {return 0;}
ret = ReadFile(hPipeN, &resposta, (DWORD)sizeof(mensagem), &n, NULL);
if (!ret || !n) {
return false;
}
PostMessage(w, WM_STARTGAME, NULL, NULL); // <- THIS GETS EXECUTED BUT NOTHINK HAPPENS AFTER
return 0;
}
答案 0 :(得分:3)
我认为这里没有任何僵局。
start_game = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadStartGame, (LPVOID)&myWindow, 0, NULL);
该行将HWND的地址传递给线程(&amp; myWindow)
HWND w = (HWND)param;
此行使用地址本身作为HWND,SendMessage将消息发送到此地址,而不是HWND。
尝试修改为
start_game = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadStartGame, (LPVOID)myWindow, 0, NULL);
答案 1 :(得分:2)
即使查看代码,我也可以马上告诉你:不要在线程之间使用SendMessage
。我建议您阅读Psychic debugging: The first step in diagnosing a deadlock is a simple matter of following the money和Preventing Hangs in Windows Applications:
在您的UI线程中使用异步窗口消息API ,尤其是将
SendMessage
替换为其中一个非阻塞对等:PostMessage
,SendNotifyMessage
或SendMessageCallback
... 跨越线程边界的任何阻塞调用都具有可导致死锁的同步属性。调用线程使用'acquire'语义执行操作,并且在目标线程'释放'该调用之前不能解除阻塞。相当多的User32函数(,例如
SendMessage
),以及许多阻止COM调用属于此类。
答案 2 :(得分:1)
对于初学者来说,你不可能首先做到这一点。引用MSDN:
调用C运行时库(CRT)的可执行文件中的线程应使用_beginthreadex和_endthreadex函数进行线程管理,而不是CreateThread和ExitThread;这需要使用CRT的多线程版本。如果使用CreateThread创建的线程调用CRT,CRT可能会在内存不足的情况下终止进程。
其次,你的线程可以是worker或UI线程,从第一种类型你不能调用大多数与窗口相关的函数,因为它没有消息泵。 DestroyWindow
就是这样。 (很多次我尝试使用MessageBox,尽管我自己的评论中有几行表示它在该函数中被禁止;)。
从工作线程,通常的方法是使用PostThreadMessage
并对UI线程做出反应。 (如果你有多个UI线程,我不知道规则,对此没有足够的勇气。)