好的,下面是一个示例,假设您创建了一个工作线程,它将一直运行到应用程序退出。用户可以暂停和恢复数据检索和记录。不需要为此使用 APC,如 cmets 中所述,而是使用同步来控制工作线程。我提议的同步对象是手动重置事件。它充当“同步布尔值”,由主 (UI) 线程设置和清除 - 如果它未发出信号,工作线程将等待它。
1.变量和初始化
BOOL bInitOK = FALSE; // Worker Thread Successfully Initialized
BOOL bChkRTD = FALSE; // Retrieval & Logging of RTD Enabled
HANDLE m_hEvt = CreateEvent(NULL, TRUE, FALSE, TRUE); // Controlling Retrieval & Logging of RTD
CWinThread *m_pLogPointThread = AfxBeginThread(AddLogPointFN, this); // Worker Thread - Created once
请注意这里的AddLogPointFN是AFX_THREADPROC函数,不是类。这将创建一个没有消息队列的线程。此外,您不需要定义和使用任何线程本地数据(即每个线程实例化的数据),因为线程将只实例化一次,即您的数据本质上是“全局的”(尽管它们可能包含在另一个线程中单实例类,如主窗口或视图)。或者,您可以使用 CreateThread() 函数和 LPTHREAD_START_ROUTINE 创建线程 - 这个是 _stdcall。该事件控制工作线程是否检查数据;它有点“复制”由用户设置的bChkRTD 变量——事件是可等待对象,而布尔变量不是。
2. 线程程序
UINT AddLogPointFN(LPVOID lParam)
{
// CLogView* variable - For convenience
CLogView* pView = (CLogView*)lParam; // Assuming lParam is CLogView
// Add one-time, resource-heavy initialization here, eg connections
.
.
bool bInit = InitConnections();
if (!bInit)
{
// Initialization Failed - Tell UI to display an error-message or exit
pView->PostMessage(USERMESSAGE_ALPNOTIFY, 1);
return 1;
}
// Initialization Successful - Tell UI to enable RTD request menus or buttons
pView->PostMessage(USERMESSAGE_ALPNOTIFY, 2);
// Wait if m_hEvt is non-signalled
while(WaitForSingleObject(pView->m_hEvt,INFINITE)==WAIT_OBJECT_0)
{
// Retrieve RTD
.
.
// Data retrieved, tell UI to update
pView->PostMessage(USERMESSAGE_ALPNOTIFY, 3, (LPARAM)p_Data);
}
return 0;
}
RTD 检索是通过等待事件对象来控制的。该事件是手动重置的,即等待函数不会重置它 - 它仅由 UI 线程设置/重置。该线程不会直接修改(全局)bInitOK 变量(这需要同步访问),而是通知 UI 线程进行设置。
3. 主线程项和例程
// Start/Stop Command and UI Update
void CLogView::OnStartStoplogger()
{
bChkRTD = !bChkRTD; // Check-box behavior, see also ON_UPDATE_COMMAND_UI
if (bChkRTD) SetEvent(m_hEvt);
else ResetEvent(m_hEvt);
}
void CLogView::OnUpdateStartStoplogger(CCmdUI *pCmdUI)
{
pCmdUI->Enable(bInitOK); // Enabled if Initialization Successful
pCmdUI->SetCheck(bChkRTD); // Checked if RTD Retrieval Enabled
}
// USERMESSAGE_ALPNOTIFY Handler
afx_msg LRESULT CLogView::OnALPNotify(WPARAM wParam, LPARAM lParam)
{
switch(wParam)
{
case 1: // Initialization Failed - Show some message or exit
.
.
break;
case 2: // Initialization Successful - Enable Start/Stop UI item
bInitOK = TRUE;
break;
case 3: // New RTD Available - Display the data
// E.g. copy the date returned from the worker thread to some local structure
CopyMyData(m_pMyData, (MY_DATA*)lParam);
GlobalFree((HGLOBAL)lParam)
UpdateData(FALSE);
break;
}
}