在主对话框退出时判断子线程是否安全退出。如果在主对话框中使用WaitForSingleObject()等待子线程退出,WaitForSingleObject()将阻断所有对话框消息循环,以致对话框消息循环阻塞界面卡死,这个不是我们预期的效果和想要完成的功能。
在主对话框函数中设置事件使其变为有信号状态。在主对话框中使用WaitForSingleObject()函数等待子线程结束,此时奇怪的一幕就会发生。WaitForSingleObject()会阻塞消息循环,故导致子线程TemPlcControllerModbusCommThread(LPVOID lParam)退出后return 0;之前的::SendMessage()消息不被主对话框所接收。
::PostMessage(pMainHwnd->GetSafeHwnd(), WM_QUIT_MDBS_COMMUNICATION_THREAD, WPARAM(pModbusConn->mPlcController.ThreadMark),0);
return 0;
mPlcController.mProEvent.SetEvent();//设定事件
WaitForSingleObject(mPlcController.mProEvent,INFINITE);//等待线程结束
UINT CDoublePathWayReflowerControllerDlg::TemPlcControllerModbusCommThread(LPVOID lParam)
{
CDoublePathWayReflowerControllerDlg* pModbusConn = (CDoublePathWayReflowerControllerDlg*)lParam;
CWnd* pMainHwnd = AfxGetApp()->GetMainWnd();
DWORD mEventQuit = 0;
CSingleLock mLoopRw(&mCommCmutex);
while (TRUE)
{
mEventQuit = WaitForSingleObject(pModbusConn->mPlcController.mProEvent.m_hObject, 0);
if (mEventQuit == WAIT_OBJECT_0)
{
break;
}
/*while (WaitForSingleObject(pModbusConn->mPlcController.modbusThreadQuit.m_hObject, 50) == WAIT_OBJECT_0)
{
printf("Wait WriteDataSet To Plc controller Finished!\n");
}*/
/*Read Write Test Begine*/
/* pModbusConn->WriteAllQbitByStep(&pModbusConn->mPlcController, NUM_OUPUT_Q, pModbusConn->mPlcDataCommTalble.Table_ReadQ_bits, QOUT_OPEN);
pModbusConn->DlgDelayUs(1);
pModbusConn->WriteAllQbitByStep(&pModbusConn->mPlcController, NUM_OUPUT_Q, pModbusConn->mPlcDataCommTalble.Table_ReadQ_bits, QOUT_CLOSE);
pModbusConn->DlgDelayUs(1);
pModbusConn->WriteQbitsByMultiByte(&pModbusConn->mPlcController, NUM_OUPUT_Q, pModbusConn->mPlcDataCommTalble.Table_WriteMulti_Qbits, pModbusConn->mPlcDataCommTalble.Table_ReadMulti_Qbits, QOUT_OPEN);
pModbusConn->DlgDelayUs(1);
pModbusConn->WriteQbitsByMultiByte(&pModbusConn->mPlcController, NUM_OUPUT_Q, pModbusConn->mPlcDataCommTalble.Table_WriteMulti_Qbits, pModbusConn->mPlcDataCommTalble.Table_ReadMulti_Qbits, QOUT_CLOSE);*/
/*pModbusConn->WriteFloatRegister(&pModbusConn->mPlcController,1000,2, pModbusConn->mPlcDataCommTalble.WriteTemFloatDataRegister, pModbusConn->mPlcDataCommTalble.Table_WriteTemDataRegisters,0);
pModbusConn->DlgDelayUs(1);*/
/*Read Write Test End*/
/*pModbusConn->mPlcDataCommTalble.Table_ReadWordRegisters[0] = 1234;
pModbusConn->WriteWordRegiste(&pModbusConn->mPlcController, 9000, 1, pModbusConn->mPlcDataCommTalble.Table_ReadWordRegisters, 0);
printf("VW9000=%X\n", pModbusConn->mPlcDataCommTalble.Table_ReadWordRegisters[0]);*/
mLoopRw.Lock();
if (mLoopRw.IsLocked())
{
if (mManualWriteData==FALSE)
{
for (int i = 1; i <= PATHA_TEMZONE_NUM; i++)
{
pModbusConn->ReadTempretureFromController(PATHA, i);
}
::SendMessage(pMainHwnd->GetSafeHwnd(), WM_UPDATE_REAL_TEMPREUTRE, WPARAM(pModbusConn->mPlcDataCommTalble.ReadTemFloatDataRegister), 0);
pModbusConn->DlgDelayUs(0);
pModbusConn->ReadIbitsByMultiByte(&pModbusConn->mPlcController, 0, NUM_INPUT_I, pModbusConn->mPlcDataCommTalble.Table_ReadMulti_Ibits);
if (pModbusConn->mhWnd != NULL)
{
::SendMessage(pModbusConn->mhWnd, WM_UPDATE_IO_INPUT_STATUS, WPARAM(pModbusConn->mPlcDataCommTalble.Table_ReadMulti_Ibits), 0);
}
pModbusConn->DlgDelayUs(0);
pModbusConn->ReadQbitsByMultiByte(&pModbusConn->mPlcController, NUM_OUPUT_Q, pModbusConn->mPlcDataCommTalble.Table_ReadMulti_Qbits);
if (pModbusConn->mhWnd != NULL)
{
::SendMessage(pModbusConn->mhWnd, WM_UPDATE_IO_OUTPUT_STATUS, WPARAM(pModbusConn->mPlcDataCommTalble.Table_ReadMulti_Qbits), 0);
}
}
else
{
SetEvent(pModbusConn->mPlcController.modbusThreadQuit);
}
}
else
{
printf("TemPlcControllerModbusCommThread Wait mCommCmutex Unlock!\n");
}
mLoopRw.Unlock();
}
pModbusConn->DlgDelayUs(100);
pModbusConn->mPlcController.ThreadMark = MDBS_THREAD_KILLER;
::PostMessage(pMainHwnd->GetSafeHwnd(), WM_QUIT_MDBS_COMMUNICATION_THREAD, WPARAM(pModbusConn->mPlcController.ThreadMark),0);
return 0;
使用MsgWaitForMultipleObjects()替代WaitForSingleObject(),下面为微软MSDN中有关MsgWaitForMultipleObjects()的详细解读。
Message Queue Functions | MsgWaitForMultipleObjectsEx | WaitForMultipleObjects
OS Versions: Windows CE 1.0 and later.
Header: Winbase.h.
Link Library: Msgque.lib.
Thisfunction returns when one of the specified objects is in the signaled state, or when the time-out interval elapses. This function does not return if there is unread input of the specified type in the queue. It returns only when new input arrives.
DWORD MsgWaitForMultipleObjects(DWORDnCount,LPHANDLEpHandles,BOOLfWaitAll,DWORDdwMilliseconds,DWORDdwWakeMask);
nCount
[in] Specifies the number of object handles in the array pointed to by pHandles. The maximum number of object handles is MAXIMUM_WAIT_OBJECTS
minus one.
pHandles
[in] Pointer to an array of object handles. For a list of the object types
whose handles can be specified, see the following Remarks section. The array can
contain handles of objects of different types.
fWaitAll
[in] Unsupported; set to FALSE.
dwMilliseconds
[in] Specifies the time-out interval, in milliseconds. The function returns if the interval elapses, even if the criteria specified by the dwWakeMask parameter have not been met. If dwMilliseconds is zero, the function
tests the states of the specified objects and returns immediately. If dwMilliseconds is INFINITE, the function's time-out interval never
elapses.
dwWakeMask
[in] Specifies input types for which an input event object handle will be
added to the array of object handles. This parameter can be any combination of
the following values.
Value |
Description |
QS_ALLEVENTS |
An input, WM_TIMER, WM_PAINT, WM_HOTKEY, or posted message is in the queue. |
QS_ALLINPUT |
Any message is in the queue. |
QS_HOTKEY |
A WM_HOTKEY message is in the queue. |
QS_INPUT |
An input message is in the queue. |
QS_KEY |
A WM_KEYUP, WM_KEYDOWN, WM_SYSKEYUP, or WM_SYSKEYDOWN message is in the queue. |
QS_MOUSE |
A WM_MOUSEMOVE message or mouse-button message (WM_LBUTTONUP, WM_RBUTTONDOWN, and so on). |
QS_MOUSEBUTTON |
A mouse-button message (WM_LBUTTONUP, WM_RBUTTONDOWN, and so on). |
QS_MOUSEMOVE |
A WM_MOUSEMOVE message is in the queue. |
QS_PAINT |
A WM_PAINT message is in the queue. |
QS_POSTMESSAGE |
A posted message (other than those just listed) is in the queue. |
QS_SENDMESSAGE |
A message sent by another thread or application is in the queue. |
QS_TIMER |
A WM_TIMER message is in the queue. |
If the function succeeds, the return value indicates the event that caused
the function to return. The successful return value is one of the following:
WAIT_OBJECT_0 to (WAIT_OBJECT_0 + nCount –1)
The return value minus WAIT_OBJECT_Zero indicates the pHandles array
index of the object that satisfied the wait.
WAIT_OBJECT_0 + nCount
New input of the type specified in the dwWakeMask parameter is available in the thread's input queue. Functions such as PeekMessage and GetMessage mark messages in the queue as old
messages. Therefore, after you call one of these functions, a subsequent call to MsgWaitForMultipleObjects will not return until new input of the
specified type arrives.
This value is also returned upon the occurrence of a system event that
requires the thread's action, such as foreground activation. Therefore, MsgWaitForMultipleObjects can return even though no appropriate input is available and even if dwWaitMask is set to 0. If this occurs, call PeekMessage or GetMessage to process the system event before trying the call to MsgWaitForMultipleObjects again.
WAIT_ABANDONED_0 to (WAIT_ABANDONED_0 + nCount –1)
The return value minus WAIT_ABANDONED_Zero indicates the pHandles
array index of an abandoned mutex object that satisfied the wait.
WAIT_TIMEOUT
The time-out interval elapsed and the conditions specified by the dwWakeMask parameter were not satisfied.
0xFFFFFFFF indicates failure. To get extended error information, call GetLastError.
The MsgWaitForMultipleObjects function is implemented as a macro that calls MsgWaitForMultipleObjectsEx, passing 0 in the dwFlags parameter.
The MsgWaitForMultipleObjects function determines whether the wait criteria have been met. If the criteria have not been met, the calling thread enters an efficient wait state, using very little processor time while waiting for the conditions of the wait criteria to be met.
Before returning, a wait function modifies the state of some types of synchronization objects. Modification occurs only for the object or objects whose signaled state caused the function to return. For example, the count of a semaphore object is decreased by one. When fWaitAll is FALSE, and multiple objects are in the signaled state, the function chooses one of the objects to satisfy the wait; the states of the objects not selected are unaffected.
The MsgWaitForMultipleObjects function can specify handles of the following object types in the pHandles array:
Event
Mutex
Semaphore
Process
Thread
Critical section
The QS_POSTMESSAGE flag is cleared when you call GetMessage or PeekMessage, whether or not you are filtering messages.
OS Versions: Windows CE 1.0 and later.
Header: Winbase.h.
Link Library: Msgque.lib.
MsgWaitForMultipleObjects | MsgWaitForMultipleObjectsEx | WaitForMultipleObjects | CreateEvent | CreateFile | PulseEvent | ResetEvent | SetEvent | Sleep
OS Versions: Windows CE 1.0 and later.
Header: Winbase.h.
Link Library: Coredll.lib.
This function returns when the specified object is in the signaled state or when the time-out interval elapses.
DWORDWaitForSingleObject( HANDLEhHandle, DWORDdwMilliseconds);
hHandle
[in] Handle to the object. For a list of the object types whose handles can
be specified, see the Remarks section.
dwMilliseconds
[in] Specifies the time-out interval, in milliseconds. The function returns
if the interval elapses, even if the object's state is nonsignaled. If dwMilliseconds is zero, the function tests the object's state and returns immediately. If dwMilliseconds is INFINITE, the function's time-out interval never elapses.
If the function succeeds, the return value indicates the event that caused
the function to return. The following table shows the possible return values.
Value |
Description |
WAIT_OBJECT_0 |
The state of the specified object is signaled. |
WAIT_TIMEOUT |
The time-out interval elapsed, and the object's state is nonsignaled. |
WAIT_FAILED indicates failure. Waiting on an invalid handle causes WaitForSingleObject to return WAIT_FAILED.
To get extended error information, call GetLastError.
Windows CE 1.0 through 2.12 do not support waiting for semaphores, change notification objects, input, and timers. Windows CE 3.0 and later support waiting for semaphores.
For Windows CE 1.0 and 1.01, this function cannot wait on process or thread handles.
The WaitForSingleObject function checks the current state of the specified object. If the object's state is nonsignaled, the calling thread enters an efficient wait state. The thread consumes very little processor time while waiting for the object state to become signaled or the time-out interval to elapse.
The time-out value needs to be a positive number between zero and 0x7FFFFFFF. The maximum time-out value not equal to infinity is 0x7FFFFFFF. The infinite time-out value is 0xFFFFFFFF. Any time-out value between 0x7FFFFFFF and 0xFFFFFFFF — that is, values from 0x80000000 through 0xFFFFFFFE — is equivalent to 0x7FFFFFFF. If you need a bigger time-out value than the maximum of 0x7FFFFFFF, use the value for infinity (0xFFFFFFFF).
Before returning, a wait function modifies the state of some types of synchronization objects. Modification occurs only for the object whose signaled state caused the function to return. For example, the count of a semaphore object is decreased by one.
The WaitForSingleObject function can wait for the following objects:
Event
Mutex
Semaphore
Process
Thread
Use caution when calling the wait functions and code that directly or indirectly creates windows. If a thread creates any windows, it must process messages. Message broadcasts are sent to all windows in the system. A thread that uses a wait function with no time-out interval may cause the system to become deadlocked. For example, the Dynamic Data Exchange (DDE) protocol and the COM function CoInitialize both indirectly create windows that can cause a deadlock. Therefore, if you have a thread that creates windows, use MsgWaitForMultipleObjects or MsgWaitForMultipleObjectsEx, rather than WaitForSingleObject.
OS Versions: Windows CE 1.0 and later.
Header: Winbase.h.
Link Library: Coredll.lib.
MsgWaitForMultipleObjects | MsgWaitForMultipleObjectsEx | WaitForSingleObject | CreateEvent | CreateFile | CreateMutex | CreateProcess | CreateThread | PulseEvent | ResetEvent | SetEvent
OS Versions: Windows CE 1.01 and later.
Header: Winbase.h.
Link Library: Nk.lib.
This function returns a value when either any one of the specified objects is in the signaled state, or the time-out interval elapses.
DWORD WaitForMultipleObjects(DWORDnCount, CONST HANDLE* lpHandles, BOOLfWaitAll, DWORDdwMilliseconds);
nCount
[in] Specifies the number of object handles in the array pointed to by lpHandles. The maximum number of object handles is MAXIMUM_WAIT_OBJECTS.
lpHandles
[in] Pointer to an array of object handles. For a list of the object types
whose handles can be specified, see the Remarks section. The array can contain
handles of objects of different types.
fWaitAll
[in] Specifies the wait type. This parameter must be set to FALSE. This
causes function to return when the state of any one of the objects set to is
signaled. The return value indicates the object whose state caused the function
to return.
dwMilliseconds
[in] Specifies the time-out interval in milliseconds. The function returns if the interval elapses, even if the conditions specified by the bWaitAll parameter are not met. If dwMilliseconds is zero, the function tests the
states of the specified objects and returns immediately. If dwMilliseconds is INFINITE, the function's time-out interval never elapses.
If the function succeeds, the return value indicates the event that caused the function to return. This value can be one of the following.
Value |
Description |
WAIT_OBJECT_0 to (WAIT_OBJECT_0 + nCount –1) |
The return value minus WAIT_OBJECT_0 indicates the lpHandles array index of the object that satisfied the wait. If more than one object became signaled during the call, this is the array index of the signaled object with the smallest index value of all the signaled objects. |
WAIT_TIMEOUT |
The time-out interval elapsed and the condition specified by the fWaitAll parameter is not satisfied. |
WAIT_FAILED indicates failure. To get extended error information, call GetLastError.
Windows CE 1.0 through 2.12 do not support waiting for semaphores, change notification objects, input, and timers. Windows CE 3.0 and later supports waiting for semaphores.
For Windows CE 1.0 and 1.01, this function cannot wait on process or thread handles.
The WaitForMultipleObjects function determines whether the wait criteria were met. If the criteria were not met, the calling thread enters an efficient wait state, consuming very little processor time while waiting for the criteria to be met.
The time-out value needs to be a positive number between zero and 0x7FFFFFFF. The maximum time-out value not equal to infinity is 0x7FFFFFFF. The infinite time-out value is 0xFFFFFFFF. Any time-out value between 0x7FFFFFFF and 0xFFFFFFFF—that is, values from 0x80000000 through 0xFFFFFFFE—is equivalent to 0x7FFFFFFF. If you need a bigger time-out value than the maximum of 0x7FFFFFFF, use the value for infinity (0xFFFFFFFF).
Before returning, a wait function modifies the state of some types of synchronization objects. Modification occurs only for the object or objects whose signaled state caused the function to return. When fWaitAll is FALSE, and multiple objects are in the signaled state, the function chooses one of the objects to satisfy the wait; the states of the objects not selected are unaffected.
The WaitForMultipleObjects function can specify handles of any of the following object types in the lpHandles array:
Event
Mutex
Process
Thread
Semaphore
Use caution when calling the wait functions and code that directly or indirectly creates windows. If a thread creates any windows, it must process messages. Message broadcasts are sent to all windows in the system. A thread that uses a wait function with no time-out interval may cause the system to become deadlocked. For example, the Dynamic Data Exchange (DDE) protocol and the COM function CoInitialize both indirectly create windows that can cause a deadlock. Therefore, if you have a thread that creates windows, use MsgWaitForMultipleObjects or MsgWaitForMultipleObjectsEx, rather than WaitForMultipleObjects.
OS Versions: Windows CE 1.01 and later.
Header: Winbase.h.
Link Library: Nk.lib.
MsgWaitForMultipleObjects | MsgWaitForMultipleObjectsEx | WaitForSingleObject | CreateEvent | CreateFile | CreateMutex | CreateProcess | CreateThread | PulseEvent | ResetEvent | SetEvent
Last updated on Wednesday, September 14, 2005
© 2005 Microsoft Corporation. All rights reserved.
void CDoublePathWayReflowerControllerDlg::MsgWaitForMultipleObjectsEx(BOOL mWaitPremise, HANDLE mEventHandle)
{
while (mWaitPremise==TRUE)
{
DWORD result;
MSG msg;
result = MsgWaitForMultipleObjects(1, &mEventHandle, FALSE, INFINITE, QS_SENDMESSAGE/*QS_ALLINPUT*/);
if (result == (WAIT_OBJECT_0))
{
break;
}
else
{
PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
DispatchMessage(&msg);
}
}
}
mPlcController.mProEvent.SetEvent();
/*Wait Modbus Communication Thread Quit safty*/
printf("Pre Wati Modbus Communication Thread Quit Safty!\n");
MsgWaitForMultipleObjectsEx(TRUE, mPlcController.ModBusThread->m_hThread);