在非 Window 的類別中做這種事可以使用 ::WaitForSingleObject() 來實作。
有個 Windows API 叫作 ::CreateEvent()
CreateEvent(lpEventAttributes, bManualReset, bInitialState, lpName);
lpEventAttributes - 屬性
需引入 SECURITY_ATTRIBUTES 結構的指標
通常為 NULL,代表此 handle 不可被繼承
bManualReset - 是否手動復原
等待接獲此事件發出的訊息後,
若為 FALSE 代表需手動復原為不發訊息,
若為 TRUE 表示等待釋放後,會自動復原為不發我息狀態
bInitialState - 初始值
以TRUE或FALSE表示初始是否發訊息
lpName - 名稱
CreateEvent 可以產生一個 Event Object
並回傳一個 HANDLE 即是這個 Event Object 的指標,
Event 有兩種狀態,發訊息與不發訊息,
可以用以下兩種改變 Event 的狀態,
::SetEvent(HANDLE); // 發訊息
::ResetEvent(HANDLE); // 不發訊息
也有其他較特殊的 API 例如
::PulseEvent(HANDLE); // 由無訊息轉換為發訊息,再瞬間轉為無訊息
在 MFC 中則是常使用包裝好的 CEvent
兩種都很方便,看心情隨意調用就行了。
範例:
若有一 Thread 必須等待某事件結束
此 Thread 即使是在執行狀態,也必須等到 g_event.SetEvent() 才會做下一行,
CEvent g_event;
UINT PowerOffThread(LPVOID pParam)
{
::WaitForSingleObject(g_event, INFINITE);
// do something
}
用於定時 1 分鐘的裝置
HANDLE g_eventGetStockDetail = CreateEvent(NULL, FALSE, FALSE, NULL);
UINT PowerOffThread(LPVOID pParam)
{
ResetEvent(g_eventGetStockDetail); // 設為不發訊息狀態
while(::WaitForSingleObject(g_eventGetStockDetail, 60 * 1000) == WAIT_TIMEOUT)
{
// Get Stock Data or GetParent()->PostMessage() to do something
if(/*記得加上停止條件,例如下午1點30分收盤*/)
{
break;
}
}
}
從外部控制停止條件的方式
HANDLE g_eventGetStock = CreateEvent(NULL, FALSE, FALSE, NULL);
UINT GetStockThread(LPVOID pParam)
{
while(::WaitForSingleObject(g_eventGetStock, 60 * 1000) != WAIT_OBJECT_0)
{
// 當g_eventGetStock為無訊息時,每分鐘執行一次
// 直到外部g_eventGetStock.SetEvent();使條件不成立即結束
}
return TRUE;
}
後來又想到第二個方法也可以從外部控制,只要在外部 ::SetEvent(g_eventGetStockDetail) 即可,while 內就不會 == TIMEOUT 便結束 loop 流程
真是小笨笨…
沒有留言:
張貼留言