2013-06-01 73 views
0

我在寫一個使用Borland C++(Delphi Forms)的多線程應用程序。我最近發現我可以在這些課程中使用Windows的消息服務的時候我所說的PostThreadMessage()函數:GetMessage的調用導致線程停止

System = new STSystem(SystemName,1000,1,NULL); 
while (PostThreadMessage(System->ThreadID,ST_MSG_SYSTEM_INIT,0,0) == 0) 
{ 
    Sleep(0); 
}; 

上面似乎工作就好了。問題在於線程執行功能內的這個進程的檢索結束:

void __fastcall STSystem::Execute() 

{ 
    ST_Message STMSG; 
    while(FStatus != Destroyed) 
    { 
     FHeartBeat++; 
     if(GetMessage(MSG,NULL,ST_MSG_SYSTEM_START,ST_MSG_SYSTEM_END)) 
     { 
      STMSG.Value = MSG->wParam; 
      if((STMSG.dSYS + (8*STMSG.dSEC) + (64*STMSG.dDEP)) == FSystemID) 
      { 
       RXMessages[RxQueueIn++] = STMSG.MSG; // Message 
       RXMessages[RxQueueIn++] = MSG->lParam; // Data 
      } 
     } 
     if(TaskList->Count>0) 
      ProcessTask(); 
     if(RxQueueIn!=RxQueueOut) 
      ProcessRxMessage(); 
     if(TxQueueIn!=TxQueueOut) 
      ProcessTxMessage(); 
     Sleep(0); 
    }; 
} 

上述工作約兩個線程週期,然後停止;線程停止,而不是程序。我試圖在FHeartbeat ++計數器之後的IF子句中使用PeekMessage()函數而不是GetMessage()函數。這可以防止線程停止,但仍然找不到在第一個代碼塊中發送的INIT消息。

我希望這個例子不是太具體。我試圖離開任何有關的事情。基本上,這是一個沒有窗口的類的消息泵。

回答

0

要發送消息到胎面它必須有一個消息隊列,在這個環節上的備註部分:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms644946(v=vs.85).aspx
可以精細reqired創建一個線程消息隊列的步驟。
順便說一句,如果PostThreadMessage返回0(FALSE),則出現錯誤,您必須檢查GetLastError返回的值。

+0

而(!的PeekMessage(MSG,NULL,WM_USER,WM_USER,PM_NOREMOVE)= 0){ 睡眠 (0); }; –

1

GetMessage()在沒有要檢索的消息時阻止調用線程。就像Luis說的那樣,你需要確保線程有一個消息隊列,然後開始向其發佈消息,並且你需要檢查PostThreadMessage()的返回值是否失敗。在線程中第一次調用任何user32.dll函數之前,線程中不會創建消息隊列。例如:

System = new STSystem(SystemName,1000,1,NULL); 
while (!System->Ready) 
    Sleep(100); 
if (!PostThreadMessage(System->ThreadID,ST_MSG_SYSTEM_INIT,0,0)) 
{ 
    DWORD err = GetLastError(); 
    //... 
} 

void __fastcall STSystem::Execute() 
{ 
    // create a message queue 
    PeekMessage(MSG, NULL, 0, 0, PM_NOREMOVE); 
    Ready = true; 

    ST_Message STMSG; 
    while(FStatus != Destroyed) 
    { 
     FHeartBeat++; 
     if(GetMessage(MSG,NULL,ST_MSG_SYSTEM_START,ST_MSG_SYSTEM_END)) // or PeekMessage() 
     { 
      STMSG.Value = MSG->wParam; 
      if((STMSG.dSYS + (8*STMSG.dSEC) + (64*STMSG.dDEP)) == FSystemID) 
      { 
       RXMessages[RxQueueIn++] = STMSG.MSG; // Message 
       RXMessages[RxQueueIn++] = MSG->lParam; // Data 
      } 
     } 
     if(TaskList->Count>0) 
      ProcessTask(); 
     if(RxQueueIn!=RxQueueOut) 
      ProcessRxMessage(); 
     if(TxQueueIn!=TxQueueOut) 
      ProcessTxMessage(); 
     Sleep(0); 
    }; 
} 
+0

像這樣:while(PeekMessage(MSG,NULL,WM_USER,WM_USER,PM_NOREMOVE)!= 0) { Sleep(0); }; –

+1

創建消息隊列時,您不需要在循環中調用PeekMessage()。您只需要撥打 即可。 –