在Remon Spekreijse 写的CserialPort类中,串口监视线程相关代码如下文,调用CSerialPort::ClosePort有时候不能监视关闭线程。
用AfxBeginThread创建的线程除了调用AfxEndThread还可以用什么函数关闭?
BOOL CSerialPort::StartMonitoring()
{
if (!(m_Thread = AfxBeginThread(CommThread, this)))
return FALSE;
TRACE("Thread started\n");
return TRUE;
}
BOOL CSerialPort::ClosePort()
{
// if the thread is alive: Kill
do
{
SetEvent(m_hShutdownEvent);
} while (m_bThreadAlive);
// if port is open , close it
if (m_hComm != NULL)
{
CloseHandle(m_hComm);
m_hComm = NULL;
}
return 1;
}UINT CSerialPort::CommThread(LPVOID pParam)
{
// Cast the void pointer passed to the thread back to
// a pointer of CSerialPort class
CSerialPort *port = (CSerialPort*)pParam;
// Set the status variable in the dialog class to
// TRUE to indicate the thread is running.
port->m_bThreadAlive = TRUE;
// Misc. variables
DWORD BytesTransfered = 0;
DWORD Event = 0;
DWORD CommEvent = 0;
DWORD dwError = 0;
COMSTAT comstat;
BOOL bResult = TRUE;
// Clear comm buffers at startup
if (port->m_hComm) // check if the port is opened
PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); // begin forever loop. This loop will run as long as the thread is alive.
for (;;)
{ bResult = WaitCommEvent(port->m_hComm, &Event, &port->m_ov); if (!bResult)
{
// If WaitCommEvent() returns FALSE, process the last error to determin
// the reason..
switch (dwError = GetLastError())
{
case ERROR_IO_PENDING:
{
// This is a normal return value if there are no bytes
// to read at the port.
// Do nothing and continue
break;
}
case 87:
{
// Under Windows NT, this value is returned for some reason.
// I have not investigated why, but it is also a valid reply
// Also do nothing and continue.
break;
}
default:
{
// All other error codes indicate a serious error has
// occured. Process this error.
port->ProcessErrorMessage("WaitCommEvent()");
break;
}
}
}
else
{
// If WaitCommEvent() returns TRUE, check to be sure there are
// actually bytes in the buffer to read.
bResult = ClearCommError(port->m_hComm, &dwError, &comstat); if (comstat.cbInQue == 0)
continue;
} // end if bResult // Main wait function. This function will normally block the thread
// until one of nine events occur that require action.
Event = WaitForMultipleObjects(3, port->m_hEventArray, FALSE, INFINITE); switch (Event)
{
case 0:
{
// Shutdown event. This is event zero so it will be
// the higest priority and be serviced first.
port->m_bThreadAlive = FALSE;
// Kill this thread. break is not needed, but makes me feel better.
AfxEndThread(100);
break;
}
case 1: // read event
{
GetCommMask(port->m_hComm, &CommEvent);
if (CommEvent & EV_CTS)
::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_CTS_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
if (CommEvent & EV_RXFLAG)
::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_RXFLAG_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
if (CommEvent & EV_BREAK)
::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_BREAK_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
if (CommEvent & EV_ERR)
::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_ERR_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
if (CommEvent & EV_RING)
::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_RING_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
if (CommEvent & EV_RXCHAR)
// Receive character event from port.
ReceiveChar(port, comstat);
break;
}
case 2: // write event
{
// Write character event from port
WriteChar(port);
break;
} } // end switch } // close forever loop return 0;
}
用AfxBeginThread创建的线程除了调用AfxEndThread还可以用什么函数关闭?
BOOL CSerialPort::StartMonitoring()
{
if (!(m_Thread = AfxBeginThread(CommThread, this)))
return FALSE;
TRACE("Thread started\n");
return TRUE;
}
BOOL CSerialPort::ClosePort()
{
// if the thread is alive: Kill
do
{
SetEvent(m_hShutdownEvent);
} while (m_bThreadAlive);
// if port is open , close it
if (m_hComm != NULL)
{
CloseHandle(m_hComm);
m_hComm = NULL;
}
return 1;
}UINT CSerialPort::CommThread(LPVOID pParam)
{
// Cast the void pointer passed to the thread back to
// a pointer of CSerialPort class
CSerialPort *port = (CSerialPort*)pParam;
// Set the status variable in the dialog class to
// TRUE to indicate the thread is running.
port->m_bThreadAlive = TRUE;
// Misc. variables
DWORD BytesTransfered = 0;
DWORD Event = 0;
DWORD CommEvent = 0;
DWORD dwError = 0;
COMSTAT comstat;
BOOL bResult = TRUE;
// Clear comm buffers at startup
if (port->m_hComm) // check if the port is opened
PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); // begin forever loop. This loop will run as long as the thread is alive.
for (;;)
{ bResult = WaitCommEvent(port->m_hComm, &Event, &port->m_ov); if (!bResult)
{
// If WaitCommEvent() returns FALSE, process the last error to determin
// the reason..
switch (dwError = GetLastError())
{
case ERROR_IO_PENDING:
{
// This is a normal return value if there are no bytes
// to read at the port.
// Do nothing and continue
break;
}
case 87:
{
// Under Windows NT, this value is returned for some reason.
// I have not investigated why, but it is also a valid reply
// Also do nothing and continue.
break;
}
default:
{
// All other error codes indicate a serious error has
// occured. Process this error.
port->ProcessErrorMessage("WaitCommEvent()");
break;
}
}
}
else
{
// If WaitCommEvent() returns TRUE, check to be sure there are
// actually bytes in the buffer to read.
bResult = ClearCommError(port->m_hComm, &dwError, &comstat); if (comstat.cbInQue == 0)
continue;
} // end if bResult // Main wait function. This function will normally block the thread
// until one of nine events occur that require action.
Event = WaitForMultipleObjects(3, port->m_hEventArray, FALSE, INFINITE); switch (Event)
{
case 0:
{
// Shutdown event. This is event zero so it will be
// the higest priority and be serviced first.
port->m_bThreadAlive = FALSE;
// Kill this thread. break is not needed, but makes me feel better.
AfxEndThread(100);
break;
}
case 1: // read event
{
GetCommMask(port->m_hComm, &CommEvent);
if (CommEvent & EV_CTS)
::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_CTS_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
if (CommEvent & EV_RXFLAG)
::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_RXFLAG_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
if (CommEvent & EV_BREAK)
::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_BREAK_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
if (CommEvent & EV_ERR)
::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_ERR_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
if (CommEvent & EV_RING)
::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_RING_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
if (CommEvent & EV_RXCHAR)
// Receive character event from port.
ReceiveChar(port, comstat);
break;
}
case 2: // write event
{
// Write character event from port
WriteChar(port);
break;
} } // end switch } // close forever loop return 0;
}
解决方案 »
- 请教Windows中键盘信息处理的几个问题。
- 用send/recv处理数据结构的发送
- 大家帮忙看看,为什么得到的strval2的值为空?
- 请教DataGrid和DatalList的有关问题??
- 我用windows media player控件在全屏模式下播放,但是我一按键或鼠标就不响应事件了为什么
- 在class wizard里有的类能显示出来?
- 我在制作滚动窗口的时候,如何使窗口内的控件也随着一起滚动,并且不能出现闪烁?急
- 紧急问题,大家来看看,一定给分
- 用键盘控制界面切换,无法切换啊。
- getopenfilename():怎么实现win2000的新的打开文件对话框风格?
- 200分求个人简历参考意见,顶者\进者\提意见好坏均欢迎 者都给分,不够再加.
- 为什么kebbd_event在一些程序里面没有效果(比如剑侠情愿)?
2、TerminateThread可以强制关闭线程,一般不建议使用这个函数,容易造成线程所用的资源无法释放,关闭之后要调用CloseHandle()函数来关闭线程句柄
要么只能用TerminateThread了,虽然危险一点
2.在入線程前Reset
3.在線程內做判斷,若Event被Set即return
4.在你想關閉線程時Set這個Event
m_pThreadWrite=AfxBeginThread(ThreadProc,(LPVOID)this);UINT CMyClass::ThreadProc(LPVOID lp)
{
CMicrophoneInput* pInput=(CMicrophoneInput*)lp;
return pInput->Run();
}
UINT CMyClass::Run()
{
HRESULT hr;
if(!InitInstance()){
TRACE("InitInstance failed\r\n";
return ExitInstance();
}
while(!IsKilling()){
//do something
}
return ExitInstance();
}
BOOL CMyClass::InitInstance()
{
m_eventKill.ResetEvent();
m_eventDead.ResetEvent();
//do something
return TRUE
}
UINT CMyClass::ExitInstance()
{
//do something
m_eventDead.SetEvent();
return 0;
}BOOL CMyClass::IsDead()
{
return WaitForSingleObject(m_eventDead,0)==WAIT_OBJECT_0;
}
BOOL CMyClass::IsKilling()
{
return WaitForSingleObject(m_eventKill,0)==WAIT_OBJECT_0;
}
在外部可以这样终止线程
//check if dead
if(!IsDead()&&m_pThreadWrite!=NULL){
m_eventKill.SetEvent();
WaitForSingleObject(m_eventDead,INFINITE);
m_pThreadWrite=NULL;
}
还是在结构里找原因