當你的線程初始化它只需要調用PeekMessage來「創建」一個消息隊列。然後另一個線程可以通過PostThreadMessage發送消息給它。此外,INVALID_THREAD_ID的錯誤代碼是您的工作線程實際退出(或從未創建)的症狀。確保您有足夠的調試流程或日誌記錄來驗證工作線程是否已創建並且不會過早退出。此外,請確保您正在檢查AfxBeginThread的返回碼,並且m_nThreadID是有效的(因爲我假設您將它初始化爲零)。
我一直在做類似的線程練習。我已經不再使用消息隊列,而是使用自己的事件和隊列進行更好的控制。
如果您不需要保證工作項目的排序,那麼另一個想法就是使用Windows「線程池」爲您完成工作。
下面是如何我通常結構C++線程類的輪廓。這只是我基於現有項目一起鞭打的東西,並不是生產代碼。但它應該展示一些關於如何管理線程生命週期的概念。
// CList is any generic "array" or "list" class (you can use std::list, CAtlArray, CSimpleArray, etc...)
// ThreadMessage is your data structure for holding data to indicate to the thread what to do
// e.g.
// struct ThreadMessage
//{
// enum type; // YOUR_CODE_TO_QUIT=0, WORK_MESSAGE=1, etc...
// workdata data;
//};
class CMyThread
{
private:
CRITICAL_SECTION m_cs; // lock such that m_queue is thread safe, can be replaced with CComAutoCriticalSection or equivalent
bool m_fNeedToExit; // signals to the worker thread that it is time to exit
HANDLE m_hEvent; // For waking up the worker thread to tell it a new message is available
HANDLE m_hThread; // handle to worker thread
HANDLE m_hStartEvent; // For the worker thread to signal back to the parent thread that is has finished initializing
bool m_fStarted; // Has Start() been called
DWORD m_dwThread; // threadID
CList<ThreadMessage> m_queue; // generic "array" of work items. Can be replaced with any list-type data structure
public:
CMyThread()
{
InitializeCriticalSection(&m_cs);
}
~CMyThread()
{
Stop();
DeleteCriticalSection(&m_cs);
}
HRESULT Start()
{
if (m_fStarted)
return S_FALSE;
// todo - check all return codes from the Create functions!
m_hEvent = CreateEvent(0,0,0,0); // unsignalled, unnamed, auto-reset event
m_hStartEvent = CreateEvent(0,0,0,0); // unsignalled, unnamed, auto-reset event
m_hThread = CreateThread(NULL, 0, CMyThread::ThreadProc, this, 0, &m_dwThreadID);
// PUT YOUR THREAD INITIALIZATION CODE HERE
// wait for the thread to intialize (you don't have to call this next line if the thread doesn't have any initialization to wait for */
WaitForSingleObject(m_hStartEvent, INFINITE);
m_fStarted = true;
return S_OK;
}
HRESULT Stop()
{
if (m_hThread)
{
m_fNeedToExit = true;
ThreadMessage quitmessage;
quitmessage.type = YOUR_CODE_TO_QUIT;
SendMessageToThread(&quitmessage);
// in a debug build, you may want to wait for X seconds and show an error message if the worker thread appears hung
WaitForSingleObject(m_hThread, INFINITE);
// cleanup
CloseHandle(m_hThread); m_hThread = NULL;
CloseHandle(m_hStartEvent); m_hStartEvent = NULL;
CloseHandle(m_hEvent); m_hEvent= NULL;
m_fStarted = true;
m_dwThread = 0;
m_queue.empty();
}
return S_OK;
}
HRESULT SendMessageToThread(Message* pMsg)
{
if (m_fStarted == false)
return E_FAIL;
EnterCriticalSection(&m_cs);
m_queue.enque(*pMsg); //push message onto queue
LeaveCriticalSection(&m_cs);
SetEvent(m_hEvent); // signal the thread to wakeup and process it's message queue
return S_OK;
}
void ThreadProcImpl()
{
// initialize thread if needed (e.g. call PeekMessage to initialize the message queue if you need one - in this implementation you don't)
// signal back to the main thread we're off and running
SetEvent(m_hThreadStarted);
while (m_fNeedToExit == false)
{
bool fGotMsg = false;
ThreadMessage msg;
EnterCriticalSection(&m_cs);
if (m_queue.size > 0)
{
msg = m_queue.deque(); // remove the first message from the queue (if any)
fGotMsg = true;
}
LeaveCriticalSection(&m_cs);
// if the queue is empty, then wait for another message to come in
if (fGotMsg == false)
{
WaitForSingleObject(m_hEvent, INFINITE); // on return m_hEvent is auto-reset to unsignalled
continue; // back to top of while loop to deque
}
if (m_fNeedToExit) // check exit condition
break;
if (msg.type == YOUR_CODE_TO_QUIT)
break;
// YOUR CODE TO HANDLE "ThreadMessage msg" goes here. (i.e. "do the work")
}
// thread cleanup code goes here (if any)
}
static DWORD __stdcall ThreadProc(void* pcontext)
{
CMyThread* pThis = (CMyThread*)pcontext;
pThis->ThreadProcImpl();
return 0;
}
};
問題是我的子類`InitInstance`函數返回與超類相同的值。 `CWinThread :: InitInstance`返回`FALSE`,這被解釋爲初始化失敗 – Casebash 2011-02-14 23:10:40