標(biāo)題:
CSerial串口類的關(guān)閉串口解決方法
[打印本頁]
作者:
heise
時(shí)間:
2014-8-18 02:06
標(biāo)題:
CSerial串口類的關(guān)閉串口解決方法
VCserialPort
類加上關(guān)閉功能————我的解決方法(轉(zhuǎn)帖)
(2010-11-2114:01:43)
轉(zhuǎn)載▼
標(biāo)簽:
串口通信
主線程
關(guān)閉功能
進(jìn)行
中止
雜談
分類:
技術(shù)資料
VCserialPort
類加上關(guān)閉功能————我的解決方法
2010
年
10
月
15
日
星期五
10:40
CSerialPort
是一個(gè)很好的串口通訊類,但它沒有關(guān)閉串口的方法,如果對(duì)這個(gè)類的實(shí)現(xiàn)原理不了解,自行編寫串口關(guān)閉方法可能會(huì)帶來如下問題:
1
、用
closehandle
方法關(guān)閉串口:由于調(diào)用類方法
StartMonitoring
后會(huì)生成一個(gè)串口通信線程,這個(gè)線程中要不停地訪問串口,這種方法會(huì)帶來明顯的錯(cuò)誤。
2
、先用
StopMonitoring
方法停止串口監(jiān)聽,然后用
closehandle
關(guān)閉串口:由于
StopMonitoring
只是將進(jìn)程掛起,這樣做將使程序結(jié)束時(shí)解構(gòu)函數(shù)無法將中止事件發(fā)送到線程,可能導(dǎo)致程序不能完全退出,主窗口關(guān)閉后仍可在進(jìn)程管理器中看到進(jìn)程。
3
、先用
SetEvent
發(fā)送中止事件給線程,等待線程結(jié)束后再用
closehandle
關(guān)閉串口,程序如下:
voidCSerialPort::ClosePort()
{
// if thethread is alive: Kill
if(m_bThreadAlive)
{
do
{
SetEvent(m_hShutdownEvent);
} while(m_bThreadAlive);
TRACE("Threadended\n");
}
if(m_szWriteBuffer != NULL)
{
delete []m_szWriteBuffer;
m_szWriteBuffer=NULL;
}
if(m_hComm)
{
CloseHandle(m_hComm);
m_hComm =NULL;
}
}
這個(gè)程序在某些應(yīng)用中可能會(huì)導(dǎo)致程序鎖死,比如要將連續(xù)、大量接收到的數(shù)據(jù)進(jìn)行實(shí)時(shí)顯示或存盤時(shí)會(huì)發(fā)生這種情況,原因是:串口通信線程每接收到一個(gè)字符,都要用
sendmessage
通知主線程,而
sendmail
是阻塞式的,如果此時(shí)主線程正在關(guān)閉串口,會(huì)用
do...while
循環(huán)連續(xù)向串口通信線程,直到串口通信線程中止為止,這個(gè)過程也是阻塞式的,此時(shí)主線程在不斷判斷串口通信線程是否中止,通信線程發(fā)來的
sendmessage
消息進(jìn)行處理,而通信線程則在等待
sendmessage
的返回,不會(huì)對(duì)主線程發(fā)來的中止信號(hào)進(jìn)行處理,從而導(dǎo)致死鎖,進(jìn)入漫長的超時(shí)等待狀態(tài)。由于消息處理及存盤、實(shí)時(shí)顯示等過程比較耗時(shí),在對(duì)連續(xù)、大量接收到的數(shù)據(jù)進(jìn)行此類操作時(shí)極易導(dǎo)致鎖死情況,導(dǎo)致這種情況的根本原因是
sendmessage
不是異步的。
了解導(dǎo)致錯(cuò)誤的原因,就可以采取針對(duì)性的措施進(jìn)行避免,比如用
postmessage
替代
sendmessage(
可能會(huì)導(dǎo)致數(shù)據(jù)丟失
)
,不使用
do...while
循環(huán)。
將上面的
ClosePort
函數(shù)修改成以下形式:
voidCSerialPort::ClosePort()
{
// if thethread is alive: Kill
if(m_bThreadAlive)
{
MSGmessage;
while(m_bThreadAlive)
{
if(::PeekMessage(&message,m_pOwner->m_hWnd,0,0,PM_REMOVE))
{
::TranslateMessage(&message);
::DispatchMessage(&message);
}
SetEvent(m_hShutdownEvent);
}
TRACE("Threadended\n");
}
if(m_szWriteBuffer != NULL)
{
delete []m_szWriteBuffer;
m_szWriteBuffer=NULL;
}
if(m_hComm)
{
CloseHandle(m_hComm);
m_hComm =NULL;
}
}
同時(shí)在
ReceiveChar
中加入對(duì)線程結(jié)束事件的判斷:
voidCSerialPort::ReceiveChar(CSerialPort* port, COMSTATcomstat)
{
BOOL bRead= TRUE;
.......
for(;;)
{
//add bylgb
//
防止死鎖
if(WaitForSingleObject(port->m_hShutdownEvent,0)==WAIT_OBJECT_0)
return;
......
}
這樣將解決死鎖問題
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1