// CSerialProcess.cpp #include "stdafx.h" #include "SerialProcess.h" //#include #include #include #include "AutoRobot.h" #ifdef _DEBUG #define new DEBUG_NEW #endif BOOL gb_send = FALSE; // 引用全局对象; extern DWORD g_dwCID; extern HWND ghWnd; extern CRITICAL_SECTION g_cs_vt; #define USE_INSERT_AUTORAISE 1 // 支持插入命令时,自增容器大小 ; #define USE_THREADRUN_INSERT 1 // 支持采集线程运行插入命令; #define USE_POSTMESSAGE 1 // 是否支持线程向窗口发送消息; /************************************************************************/ /* 函数:构造函数 */ /************************************************************************/ CSerialProcess::CSerialProcess( ) { m_hCom = INVALID_HANDLE_VALUE; m_bOpen = FALSE; m_hRunCtrl = NULL; m_hCollectCtrl = NULL; m_hResponsetime = NULL; m_bCollected = FALSE; m_nResponseTime = 200; // 默认响应时间500ms; m_nAFrequency = 1000; // 默认采集频率3000ms; m_iSLSize = 0; // 如何设置得太小了,会在线程里出现第m_iSLSize中断几秒的现象; // 这个size可以在构造时传入; // ccomprocess cp( int nszie ); // m_iSLSize = nSize; // m_iSLSize = 40; //m_sendlist.reserve(m_iSLSize); // 预设容器最大容量; } /************************************************************************/ /* 函数:析构函数 */ /************************************************************************/ CSerialProcess::~CSerialProcess() { CloseComm(); } /************************************************************************/ /* 函数:设置容器大小; 参数: nSize: 要设置的值; */ /************************************************************************/ void CSerialProcess::SetSize(const int &nSize) { m_iSLSize = nSize; m_sendlist.reserve(nSize); } /************************************************************************/ /* 函数:自增容器大小 */ /************************************************************************/ void CSerialProcess::RaiseSize() { m_sendlist.reserve(++m_iSLSize); } /************************************************************************/ /* 函数:打开串口; 参数: iCommPort: 串口号; iRate: 波特率; iDataBit: 数据位; iStopBit: 停止位; iParity: 校验码; iResponsetime: 响应时间; iInterval: 采集频率; */ /************************************************************************/ BOOL CSerialProcess::OpenComm( const int &iCommPort, // 1.串口; const int &iRate, // 2.波特率; const int &iDataBit, // 3.数据位; const int &iStopBit, // 4.停止位; const int &iParity, // 5.校验码; const int &iResponsetime, // 6.响应时间; const int &iInterval) // 7.采集频率; { m_bOpen = FALSE; //ASSERT(iCommPort!=0); // 这个在debug下会出错,很奇怪?iCommPort的值明明是不是为0,却依旧在Debug下出错了. if(iCommPort == 0) return FALSE; int temp=0; char tmp[20]="\\\\.\\com"; char buffer[20]; m_iPort = iCommPort; _itoa(m_iPort,buffer,10); strcat(tmp,buffer); // 1.打开指定串口 m_hCom = CreateFile( tmp, // 串口名称(COMx) GENERIC_READ | GENERIC_WRITE, // 串口属性为可读/写 0, // 串口设备必须被独占性的访问 NULL, // 无安全属性 OPEN_EXISTING, // 串口设备必须使用OPEN_EXISTING参数 NULL , // 同步式 I/O NULL // 对于串口设备而言此参数必须为0 ); if(m_hCom == INVALID_HANDLE_VALUE) { // 如果该串口不存在或者正被另外一个应用程序使用, 则打开失败,程序退出 LOG4C((LOG_NOTICE,"串口损坏或正在使用,打开串口%d失败",iCommPort)); return FALSE; } m_nResponseTime = iResponsetime; m_nAFrequency = iInterval; BOOL result; // 2.设置端口的I/O缓冲区大小; result = SetupComm(m_hCom,1024,1024); ASSERT(result); if(!result) return FALSE; // 3.清除端口I/O;(清除接收/发送缓冲区) result = PurgeComm(m_hCom,PURGE_TXCLEAR|PURGE_RXCLEAR); ASSERT(result); if(!result) return FALSE; // 4.设置串口参数:波特率、数据位、校验位、停止位等信息(DCB结构体) COMMTIMEOUTS timeout; DCB dcb; // 5.获取该端口的默认参数 result = GetCommState(m_hCom, &dcb); ASSERT(result); if(!result) return FALSE; // 6.修改串口参数; dcb.Parity = iParity; if(dcb.Parity == NOPARITY) dcb.fParity = FALSE; else dcb.fParity = TRUE; dcb.BaudRate = iRate; dcb.ByteSize = iDataBit; dcb.StopBits = iStopBit; if(dcb.ByteSize == 8) dcb.StopBits = ONESTOPBIT; // 7.重新设置参数 result = SetCommState(m_hCom, &dcb); ASSERT(result); if(!result) return FALSE; // 8.获取该端口的默认超时参数 result = GetCommTimeouts(m_hCom, &timeout); ASSERT(result); if(!result) return FALSE; // 9.修改超时结构; timeout.ReadIntervalTimeout = MAXDWORD; timeout.ReadTotalTimeoutMultiplier = 0; timeout.ReadTotalTimeoutConstant = 0; timeout.WriteTotalTimeoutMultiplier = 0; timeout.WriteTotalTimeoutConstant = 0; // 10.重新设置端口的默认超时参数 result = SetCommTimeouts(m_hCom,&timeout); ASSERT( result ); if( !result ) return FALSE; m_bOpen = TRUE; // 11.创建一永久性无信号事件,用于ReadFile前设备的响应时间等待; m_hResponsetime = CreateEvent(NULL,TRUE,FALSE,NULL); // 无信号事件; return TRUE; } /************************************************************************/ /* 函数:关闭串口,并释放资源; */ /************************************************************************/ BOOL CSerialProcess::CloseComm() { SetEvent(m_hFrequencyCtrl); gb_send = TRUE; Sleep(50); // 等待最后一次SendMessage完成; if ( m_hCollectCtrl != NULL) if ( WaitForSingleObject( m_hCollectCtrl ,INFINITE) == WAIT_OBJECT_0) ResetEvent(m_hCollectCtrl); if ( m_hRunCtrl != NULL ) { SetEvent(m_hRunCtrl); if ( m_hThreaObj != NULL) { if (WaitForSingleObject(m_hThreaObj,INFINITE) != WAIT_FAILED) { CloseHandle(m_hThreaObj); m_hThreaObj = NULL; m_bCollected = FALSE; } } CloseHandle( m_hRunCtrl ); m_hRunCtrl = NULL; } if ( m_hCollectCtrl != NULL) { CloseHandle(m_hCollectCtrl); m_hCollectCtrl = NULL; } RemoveAllSendCommand(); RemoveAllRecvCommand(); m_bOpen = FALSE; if( m_hCom != INVALID_HANDLE_VALUE ) { BOOL bResult = CloseHandle( m_hCom ); if( !bResult ) { gb_send = FALSE; return FALSE; } m_hCom = INVALID_HANDLE_VALUE; } if ( m_hResponsetime ) { CloseHandle(m_hResponsetime); m_hResponsetime = NULL; } if ( m_hFrequencyCtrl ) { CloseHandle(m_hFrequencyCtrl); m_hFrequencyCtrl = NULL; } gb_send = FALSE; LOG4C((LOG_NOTICE,"关闭串口成功")); return TRUE; } /************************************************************************/ /* 函数:对串口进行读取数据; 参数: pBuf: 存储读串口时返回的数据; len: 读串口数据的长度; 返回值:返回实际串口读到的长度; */ /************************************************************************/ int CSerialProcess::Read(BYTE *pBuf, int len) { //DWORD nTick = GetTickCount(); if(m_hCom == INVALID_HANDLE_VALUE) return 0; if( pBuf == NULL || !::AfxIsValidAddress(pBuf, len, FALSE ) ) return 0; if( !m_bOpen ) return 0; BOOL bReadStatus; DWORD dwBytesRead, dwErrorFlags; COMSTAT ComStat; ClearCommError( m_hCom, &dwErrorFlags, &ComStat ); if ( WaitForSingleObject(m_hResponsetime,m_nResponseTime) == WAIT_TIMEOUT) ClearCommError(m_hCom,&dwErrorFlags,&ComStat); if( !ComStat.cbInQue ) return( 0 ); dwBytesRead = (DWORD) ComStat.cbInQue; if( len < (int) dwBytesRead ) dwBytesRead = (DWORD) len; // ReadFile成功读到数据,返回非0值,否则返回0; bReadStatus = ReadFile( m_hCom, pBuf, dwBytesRead, &dwBytesRead , NULL); #if 0 if( !bReadStatus ) { PurgeComm(m_hCom, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); return 0; } PurgeComm(m_hCom, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); return( (int) dwBytesRead ); #else PurgeComm(m_hCom, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); return (bReadStatus ? dwBytesRead : 0); #endif } /************************************************************************/ /* 函数:对串口进行写数据; 参数: pBuf: 写串口的数据; len: 写串口的数据长度; 返回值:返回实现写串口的长度; */ /************************************************************************/ int CSerialProcess::Write(const BYTE *pBuf, int len) { if( !m_bOpen ) return 0; if(m_hCom == INVALID_HANDLE_VALUE || len<=0) return 0; DWORD dwResult = 0; BOOL bResult = WriteFile( m_hCom, pBuf, (DWORD)len, &dwResult, NULL ); if(bResult) return dwResult; else return 0; } // 挂起之前,得让采集线程完成一次采集.(Write与read) /************************************************************************/ /* 函数:外掊接口函数:写命令; 参数: szCommand: 要对串口进行写的数据; iLen: 要对串口进行写的数据长度; iAddr: 串口地址; */ /************************************************************************/ BOOL CSerialProcess::SetCommand(const BYTE *szCommand, int iLen, int iAddr) { if( !m_bOpen ) return 0; if(m_hCom == INVALID_HANDLE_VALUE ) return 0; SetEvent(m_hFrequencyCtrl); gb_send = TRUE; Sleep(50); BOOL bResult = FALSE; if ( m_hCollectCtrl != NULL) { //while ( WaitForSingleObject( m_hCollectCtrl,INFINITE) == WAIT_OBJECT_0 )// while ( WaitForSingleObject( m_hCollectCtrl,500) == WAIT_OBJECT_0 )// { ResetEvent( m_hCollectCtrl ); // **其实这一步可以不需要了,只有将m_hCollectCtrl信号获取了就可以了; // **那样,即使线程在运行,也不会对串口进行读写操作了; ::SuspendThread( m_hThreaObj ); Sleep(3000); bResult = TRUE; // 挂起线程后,进行设置; int RWlen = Write(szCommand,iLen); #if USE_POSTMESSAGE SendMessage(ghWnd,WM_SHOWWRITEDATA,RWlen,(LPARAM)szCommand); #endif BYTE temp[1024] = {0}; int RRlen = Read(temp,1024); #if USE_POSTMESSAGE SendMessage(ghWnd,WM_SHOWREADDATA,RRlen,(LPARAM)temp); #endif // 设置完毕,恢复线程; ::ResumeThread( m_hThreaObj ); SetEvent( m_hCollectCtrl ); break; } } else { bResult = TRUE; Write(szCommand,iLen); BYTE temp[1024] = {0}; Read(temp,1024); } gb_send = FALSE; ResetEvent(m_hFrequencyCtrl); return bResult; } /************************************************************************/ /* 函数:采集线程(关于线程,如果可以,应该使线程尽量简单,这样稳定性高于一切); 参数: lpParamter: 类对象本身; 注意: 1.Sendmessage在线程里,会使线程不稳定.因为SendMessage是阻塞的,要等待函数完成才返回,造成线程等待,CPU高涨; 所以在线程中,最好使用PostMessage或PostThreadMessage; 2.在线程外部动态 添加命 令或 删除命令,会使线程对vector的遍历产生影响,迭代器会指乱,有可能会产生线程内for死循环; 所以,禁止外部在线程运行时操作容器; */ /************************************************************************/ DWORD WINAPI CSerialProcess::CollectThreadProc(LPVOID lpParamter) { CSerialProcess *pCommProc = (CSerialProcess*)lpParamter; if ( pCommProc->m_hCom == NULL || pCommProc->m_hCom == INVALID_HANDLE_VALUE ) return 0; if ( pCommProc->m_sendlist.size() == 0 ) return 0; HANDLE hRunCtrl = pCommProc->m_hFrequencyCtrl; vector ::iterator it_SendCommand; vector ::iterator it_RecvMessage; STSendCommand ST_SendCommand = {0}; STRecvMessage ST_RecvMessage = {0}; do { for ( it_SendCommand = pCommProc->m_sendlist.begin(); it_SendCommand != pCommProc->m_sendlist.end(); it_SendCommand++) { if ( WaitForSingleObject( pCommProc->m_hCollectCtrl ,10) == WAIT_OBJECT_0) { ResetEvent( pCommProc->m_hCollectCtrl ); ST_SendCommand = *it_SendCommand; int iRWLine = pCommProc->Write( ST_SendCommand.bySend, ST_SendCommand.iSLen ); #if USE_POSTMESSAGE if( !gb_send )// 线程给窗口发送消息,最好不要用PostThreadMessage,直接使用PostMessage; PostMessage(ghWnd,WM_SHOWWRITEDATA,iRWLine,(LPARAM)ST_SendCommand.bySend); #endif // 是否保存返回的数据; if ( ST_SendCommand.bRecv == TRUE) { ZeroMemory(&ST_RecvMessage,sizeof(STRecvMessage)); ST_RecvMessage.iPort = pCommProc->m_iPort; ST_RecvMessage.iAddr = ST_SendCommand.iAddr; ST_RecvMessage.dwSID = ST_SendCommand.dwSID; ST_RecvMessage.iRLen = 0; memcpy( ST_RecvMessage.szCheck, ST_SendCommand.szCheck, strlen(ST_SendCommand.szCheck) ); memcpy( ST_RecvMessage.szMark, ST_SendCommand.szMark, strlen(ST_SendCommand.szMark) ); ST_RecvMessage.iRLen = pCommProc->Read(ST_RecvMessage.byRecv,MAX_RECVSIZE); #if USE_POSTMESSAGE if( !gb_send ) PostMessage(ghWnd,WM_SHOWREADDATA,(WPARAM)&ST_RecvMessage,0); #endif // .判断相应的数据元素是否存在; BOOL bExist = FALSE; if( g_vtRecv.size() != 0) { for( it_RecvMessage = g_vtRecv.begin(); it_RecvMessage != g_vtRecv.end(); it_RecvMessage++) { if( ST_RecvMessage.dwSID == ((STRecvMessage)*it_RecvMessage).dwSID ) { // 若存在,直接赋值; EnterCriticalSection( &g_cs_vt ); *it_RecvMessage = ST_RecvMessage;//memcpy(it_RecvMessage,&ST_RecvMessage,sizeof(STRecvMessage)); LeaveCriticalSection( &g_cs_vt ); bExist = TRUE; break; } } } else // 第一次插入; { bExist = TRUE; EnterCriticalSection( &g_cs_vt ); g_vtRecv.push_back( ST_RecvMessage ); LeaveCriticalSection( &g_cs_vt ); } if( !bExist ) // 不存在; { EnterCriticalSection( &g_cs_vt ); g_vtRecv.push_back( ST_RecvMessage ); LeaveCriticalSection( &g_cs_vt ); } } else { BYTE temp[1024] = {0}; int iRRlen = pCommProc->Read(temp,1024); #if 0 if( !gb_send ) PostMessage(ghWnd,WM_SHOWREADDATA,iRRlen,(LPARAM)temp); #endif } SetEvent( pCommProc->m_hCollectCtrl ); // 信号在这里设置为有,使线程能够完成一次数据采集; } else { LOG4C((LOG_NOTICE,"->线程内循环被停止")); break;//如果事件无信号,直接退出循环,解决for循环的无效次数; } // 线程等待采集时间过后,才进行采集(采集频率); WaitForSingleObject( hRunCtrl,pCommProc->m_nAFrequency ); } }while (WaitForSingleObject(pCommProc->m_hRunCtrl,10) != WAIT_OBJECT_0); // 这样使用线程,!= WAIT_OBJECT_0 在结束线程时,比使用== WAIT_TIMEOUT要快结束 ; //while (WaitForSingleObject(pCommProc->m_hRunCtrl,10) == WAIT_TIMEOUT); // 这里等待的时间不能为0,如果为0就马上返回, // 对线程的控制就变得有点缓慢了; LOG4C((LOG_NOTICE,"线程结束")); return 0; } /************************************************************************/ /* 函数:启动采集线程; */ /************************************************************************/ int CSerialProcess::AutoCollect() { if ( m_bCollected ) return 0; if ( m_hCom == NULL || m_hCom == INVALID_HANDLE_VALUE ) return 0; m_hRunCtrl = CreateEvent(NULL,TRUE,FALSE,NULL); // 无信号事件; if ( m_hRunCtrl == NULL ) return -1; m_hCollectCtrl = CreateEvent(NULL, TRUE ,TRUE ,NULL); if ( m_hCollectCtrl == NULL ) return -1; m_hFrequencyCtrl = CreateEvent(NULL,TRUE,FALSE,NULL); // 无信号事件; if ( m_hFrequencyCtrl == NULL ) return -1; m_hThreaObj = CreateThread(NULL,0,CollectThreadProc,this,0,&m_dwThreadID); if ( m_hThreaObj == NULL ) return -1; m_bCollected = TRUE; return 0; } /************************************************************************/ /* 函数:停止采集线程; */ /************************************************************************/ int CSerialProcess::StopCollect() { if ( m_hCom == NULL || m_hCom == INVALID_HANDLE_VALUE ) return 0; if ( m_hRunCtrl ) { SetEvent( m_hRunCtrl ); } if (WaitForSingleObject(m_hRunCtrl,INFINITE) != WAIT_TIMEOUT) { CloseHandle(m_hThreaObj); m_hThreaObj = NULL; } CloseHandle( m_hRunCtrl ); m_hRunCtrl = NULL; CloseHandle( m_hCollectCtrl ); m_hCollectCtrl = NULL; m_bCollected = FALSE; return 0; } /************************************************************************/ /* 函数:插入发送命令; 参数: szCommand: 要插入的数据; iLen: 要插入的数据长度; iAddr: 串口地址; szMark: 命令的特征码; szCheck: 命令的校验方式; iSNum: 命令的发送顺序; bRecv: 是否保存命令读取的数据; 注意: 1.对命令的添加,会影响到采集线程的安全性与稳定性,建议在添加前,先停止线程; 盖因线程for循环时,有可能在插入新的元素后,迭代器指向的元素就不是下一个,出现漏取的现象; 所以,要么在for完整循环后插入元素,要么停止线程; */ /************************************************************************/ int CSerialProcess::InsertCommand(const BYTE *szCommand, int iLen, int iAddr,const char *szMark, const char *szCheck, int iSNum, bool bRecv) { #if !USE_THREADRUN_INSERT if ( m_bCollected ) { return -1; } #endif if( !m_bOpen ) { LOG4C((LOG_NOTICE,"串口未打开")); return 0; } if(m_hCom == INVALID_HANDLE_VALUE ) { LOG4C((LOG_NOTICE,"串口句柄无效")); return 0; } vector ::const_iterator it_SendCommand; for ( it_SendCommand = m_sendlist.begin(); it_SendCommand != m_sendlist.end(); it_SendCommand++ ) { STSendCommand ST_SendCommand = *it_SendCommand; #if 0 // 应用命令特征码来作比较 ; if ( strcmp( (char*)szCommand,(char*)(ST_SendCommand.bySend)) == 0 ) // 这里的比较 有问题,'0'隔开了两部分,前相等,后不相等. { LOG4C((LOG_NOTICE,"命令已存在!")); return -1; } #else if ( memcmp((char*)szCommand,(char*)(ST_SendCommand.bySend),iLen) == 0) { LOG4C((LOG_NOTICE,"命令已存在!")); return -1; } #endif } // before it ,check the command wasn't exist; STSendCommand ST_SendCommand ={0}; //ST_SendCommand.iSNum = iSNum; ST_SendCommand.bRecv = bRecv; ST_SendCommand.iSLen = iLen; ST_SendCommand.dwSID = g_dwCID++; ST_SendCommand.iAddr = iAddr; //memset( ST_SendCommand.szMark, 0, MAX_MARKSIZE ); memcpy( ST_SendCommand.szMark, szMark, strlen(szMark) ); //memset( ST_SendCommand.bySend, 0, MAX_SENDSIZE ); memcpy( ST_SendCommand.bySend, szCommand, iLen ); memcpy(ST_SendCommand.szCheck,szCheck,strlen(szCheck)); #if !USE_INSERT_AUTORAISE if ( m_sendlist.size() == m_sendlist.capacity() ) { LOG4C((LOG_NOTICE,"插入的容器容量小 = %d,扩大10",m_sendlist.capacity())); m_sendlist.resize(m_sendlist.capacity() + 10); } #endif if ( m_bCollected ) { LOG4C((LOG_NOTICE,"线程在运行当中,添加命令")); if ( m_hCollectCtrl != NULL) { gb_send = TRUE; Sleep(50); // 等待SendMessage完成最后一次操作; SetEvent(m_hCollectCtrl); while ( WaitForSingleObject( m_hCollectCtrl,INFINITE) == WAIT_OBJECT_0 ) { ResetEvent( m_hCollectCtrl ); ::SuspendThread( m_hThreaObj ); Sleep(100); m_sendlist.push_back( ST_SendCommand ); LOG4C((LOG_NOTICE,"线程在运行当中,添加命令结束")); ::ResumeThread( m_hThreaObj ); SetEvent( m_hCollectCtrl ); break; } gb_send = FALSE; } } else m_sendlist.push_back( ST_SendCommand ); return 0; } /************************************************************************/ /* 函数:删除指定的命令,同时删除数据池中对应的元素; 参数: szCommand: 具体的命令; 注意: 1.对命令的删除,会影响到采集线程的安全性与稳定性,建议在删除前,先停止线程 */ /************************************************************************/ int CSerialProcess::RemoveCommand(const BYTE *szCommand) { #if !USE_THREADRUN_INSERT if ( m_bCollected ) { return -1; } #endif vector ::iterator it_SendCommand; for ( it_SendCommand = m_sendlist.begin(); it_SendCommand != m_sendlist.end(); it_SendCommand++ ) { STSendCommand ST_SendCommand = *it_SendCommand; if ( strcmp( (char*)szCommand,(char*)(ST_SendCommand.bySend)) == 0 ) { m_sendlist.erase(it_SendCommand); // 必须得先删除发送的命令,才可以删除数据池的元素; vector ::iterator it_RecvMessage; for ( it_RecvMessage = g_vtRecv.begin(); it_RecvMessage != g_vtRecv.end(); it_RecvMessage++) { STRecvMessage ST_RecvMessage = *it_RecvMessage; if ( ST_RecvMessage.dwSID = ST_SendCommand.dwSID) { g_vtRecv.erase(it_RecvMessage); break; } } break;; } } return 0; } /************************************************************************/ /* 函数:删除该地址下所有设备命令,并且也删除对应数据池的元素; 参数: addr: 指定的设备地址; 注意: 1.对命令的删除,会影响到采集线程的安全性与稳定性,建议在删除前,先停止线程 */ /************************************************************************/ void CSerialProcess::RemoveDeivce(const int &addr) { #if !USE_THREADRUN_INSERT if ( m_bCollected ) { return; } #endif if( !m_bOpen ) { LOG4C((LOG_NOTICE,"串口未打开")); return ; } if(m_hCom == INVALID_HANDLE_VALUE ) { LOG4C((LOG_NOTICE,"串口句柄无效")); return ; } gb_send = TRUE; Sleep(50); // 等待SendMessage完成最后一次操作; if ( m_hCollectCtrl != NULL) { SetEvent(m_hCollectCtrl); while ( WaitForSingleObject( m_hCollectCtrl,INFINITE) == WAIT_OBJECT_0 ) { ResetEvent( m_hCollectCtrl ); ::SuspendThread( m_hThreaObj ); Sleep(100); vector ::iterator it_SendCommand; for ( it_SendCommand = m_sendlist.begin(); it_SendCommand != m_sendlist.end(); ) { STSendCommand ST_SendCommand = *it_SendCommand; if ( ST_SendCommand.iAddr == addr) { vector ::iterator it_RecvMessage; for ( it_RecvMessage = g_vtRecv.begin(); it_RecvMessage != g_vtRecv.end(); it_RecvMessage++) { STRecvMessage ST_RecvMessage = *it_RecvMessage; if ( ST_RecvMessage.dwSID = ST_SendCommand.dwSID) { g_vtRecv.erase(it_RecvMessage); break; } } it_SendCommand = m_sendlist.erase(it_SendCommand); LOG4C((LOG_NOTICE,"串口%d 删除地址%d命令成功",m_iPort,addr)); } else it_SendCommand++; } // 设置完毕,恢复线程; ::ResumeThread( m_hThreaObj ); SetEvent( m_hCollectCtrl ); break; } } gb_send = FALSE; LOG4C((LOG_NOTICE,"删除设备完成")); } /************************************************************************/ /* 函数:返回容器的大小; */ /************************************************************************/ int CSerialProcess::GetCommandsCount() { return m_sendlist.size(); } /************************************************************************/ /* 函数:删除所有发送命令; 注意: 1.erase的返回值是迭代器指向的下一元素,for循环不需要迭代器++自增; 2.对命令的删除,会影响到采集线程的安全性与稳定性; */ /************************************************************************/ void CSerialProcess::RemoveAllSendCommand() { vector::iterator it_SendCommand; for ( it_SendCommand = m_sendlist.begin(); it_SendCommand != m_sendlist.end();) it_SendCommand = m_sendlist.erase(it_SendCommand); } /************************************************************************/ /* 函数:删除该串口在数据池中的元素; 注意: 1.erase的返回值是迭代器指向的下一元素; 如果条件真,删除的元素将erase的返回值指向迭代器本身,否则自增++; 2.对数据池的操作,会影响到采集线程的安全性与稳定性; */ /************************************************************************/ void CSerialProcess::RemoveAllRecvCommand() { vector::iterator it_RecvMessage; STRecvMessage ST_RecvMessage; for ( it_RecvMessage = g_vtRecv.begin(); it_RecvMessage != g_vtRecv.end(); ) { ST_RecvMessage = *it_RecvMessage; if ( m_iPort == ST_RecvMessage.iPort ) { EnterCriticalSection( &g_cs_vt ); it_RecvMessage = g_vtRecv.erase(it_RecvMessage); LeaveCriticalSection( &g_cs_vt ); } else it_RecvMessage++ ; } }