用过CSerialPort类的进

时间:2021-07-26 21:40:47
UINT CSerialPort::CommThread(LPVOID pParam)//线程启动函数
{
CSerialPort *port=(CSerialPort*)pParam;
port->m_bThreadAlive=true;
DWORD BytesTransfered=0;
DWORD Event=0;
DWORD CommEvent=0;
DWORD dwError=0;
COMSTAT comstat;
BOOL bResult=true;
DWORD error=0;
if(port->m_hComm)
{
//PurgeComm(port->m_hComm,PURGE_RXCLEAR|PURGE_TXCLEAR|PURGE_RXABORT|PURGE_TXABORT);
ClearCommError(port->m_hComm,&error,&comstat);
SetCommMask(port->m_hComm,port->m_dwCommEvents);//设置通信事件
for(;;)
{
bResult=WaitCommEvent(port->m_hComm,&Event,&port->m_ov);
if(!bResult)
{

switch(dwError=GetLastError())
{
case ERROR_IO_PENDING:
break;//this is a normal value if there are no bytes to read at the port.do nonthing and continue
case 87:
break;
default:
{
port->ProcessErrorMessage("WaitCommEvent");
break;
}
}
}
else
{
bResult=ClearCommError(port->m_hComm,&dwError,&comstat);
if(comstat.cbInQue==0)
continue;
}
Event=WaitForMultipleObjects(3,port->m_hEventArray,FALSE,INFINITE);//应该是阻塞在这 现在返回了句柄无效???
switch(Event)
{
case 0:
{
  AfxMessageBox("shut Event");
  port->m_bThreadAlive=false;
  AfxEndThread(100);// 杀死线程
  break;
}
case 1://read event
{
      AfxMessageBox("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)
   ReceiveChar(port,comstat);
   break;

}  
case 2://write event
{
                    AfxMessageBox("write Event");
WriteChar(port);
break;
}
default:
{

CString error;
error.Format("%d",GetLastError());
                AfxMessageBox("WaitForMultipleObjects出错\n"+error);
        port->m_bThreadAlive=false;
    AfxEndThread(100);// 杀死线程
  break;
return -1;
}

}
}

}
return 0;
}


问题在WaitForMultipleObjects(3,port->m_hEventArray,FALSE,INFINITE);//调用一直出错,打印错误信息是句柄无效
然后我单个句柄进行调用,结果是每一个的无效???按理说应该是阻塞在这。。。。
请求高手指点?????急???

8 个解决方案

#1


线程定义成 static 型了么?

#2


1.在CSerialPort类里面 线程好像没有定义成static的
2. 为什么要定义成STATIC的了?

#3


肯定是你自己改动什么地方改错了,如果你一点不改拿过来用不可能有这个错误

#4


CSerialPort最新版
http://www.naughter.com/serialport.html
有例子,照着做就是了!

#5


BOOL CSerialPort::InitComm(CWnd* pPortOwner,
   UINT portnr,
   UINT baud,
   char parity,
   UINT databits,
   UINT stopbits,
   DWORD dwCommEvents,
   UINT writebuffersize)
{
assert(portnr>0 && portnr<5);
assert(pPortOwner!=NULL);

//if the thread is alive :kill
if(m_bThreadAlive)
{
do
{
SetEvent(m_hShutdownEvent);
}while(m_bThreadAlive);
} TRACE("Thread end!\n");

//creat events
if(m_ov.hEvent!=NULL)
ResetEvent(m_ov.hEvent);
else m_ov.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);//人工重置事件

if(m_hWriteEvent!=NULL)
{
ResetEvent(m_hWriteEvent);
}
else m_hWriteEvent=CreateEvent(NULL,TRUE,FALSE,NULL);//都是属于没有信号状态

if(m_hShutdownEvent!=NULL)
ResetEvent(m_hShutdownEvent);
else m_hShutdownEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
    
m_hEventArray[0]=m_hShutdownEvent;//highest priority
m_hEventArray[1]=m_ov.hEvent;
m_hEventArray[2]=m_hWriteEvent;

//init critical section
InitializeCriticalSection(&this->m_csCommunicationSync);
//set buffersize for writting and save the ower
m_pOwner=pPortOwner;
if(m_szWriteBuffer!=NULL)
    {
delete [] m_szWriteBuffer;
}

m_szWriteBuffer=new char[writebuffersize];
m_nPortNr=portnr;
m_nWriteBufferSize=writebuffersize;
m_dwCommEvents=dwCommEvents;
BOOL bResult=false;
char *szPort=new char[50];
char *szBaud=new char[50];

EnterCriticalSection(&this->m_csCommunicationSync);
//进入临界区
//   if   the   port   is   already   opened:   close   it   
    if(m_hComm!=NULL)
{
CloseHandle(m_hComm);
m_hComm=NULL;
}
//   prepare   port   strings   
     sprintf(szPort,"COM%d",portnr);
 sprintf(szBaud,"baud=%d parity=%c data=%d stop=%d",baud,parity,databits,stopbits);

 
  //   get   a   handle   to   the   port  
  m_hComm=CreateFile(szPort,GENERIC_READ|GENERIC_WRITE,
  0,//端口只能独享
  NULL,//默认的安全属性
  OPEN_EXISTING,
  FILE_FLAG_OVERLAPPED,
  0);//template must be 0 for comm devices


  if(m_hComm==INVALID_HANDLE_VALUE)
  {
  delete [] szPort;
  delete [] szBaud;
  return false;
  }
  if(!SetupComm(m_hComm,1024,512))
  {
         AfxMessageBox("设置缓冲区失败");
 return false;
  }
   PurgeComm(m_hComm,PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);

  //set timeout values
  m_CommTimeouts.ReadIntervalTimeout=MAXDWORD;   
  m_CommTimeouts.ReadTotalTimeoutMultiplier=0;   
  m_CommTimeouts.ReadTotalTimeoutConstant  = 0;   
  m_CommTimeouts.WriteTotalTimeoutMultiplier = 0;   
  m_CommTimeouts.WriteTotalTimeoutConstant=5000; 
  

  if(SetCommTimeouts(m_hComm,&m_CommTimeouts))
  {
  if(SetCommMask(m_hComm,dwCommEvents))
  {
  if(GetCommState(m_hComm,&m_dcb))
  {
             m_dcb.fDtrControl=RTS_CONTROL_ENABLE;//   set   RTS   bit   high! 
 m_dcb.fBinary=true;
 m_dcb.EofChar=0x1a;
 m_dcb.DCBlength=sizeof(DCB);
 m_dcb.fInX=true;
         m_dcb.fOutX=true;
         m_dcb.XoffChar=XOFF;
         m_dcb.XonChar=XON;
         m_dcb.XoffLim=256;
         m_dcb.XonLim=256;
 if(BuildCommDCB(szBaud,&m_dcb))
 {
 if(SetCommState(m_hComm,&m_dcb));
 else
 ProcessErrorMessage("SetCommState");
 }
 else ProcessErrorMessage("BuildCommDCB");

  }
  else ProcessErrorMessage("GetCommState()");
  }
  else ProcessErrorMessage("SetCommMask()");
  }
  else ProcessErrorMessage("SetCommTimeouts()");
 
  delete [] szPort;
  delete [] szBaud;
    
  LeaveCriticalSection(&m_csCommunicationSync);   
  TRACE("Initialisation   for   communicationport   %d completed.\nUse   Startmonitor   to   communicate.\n",   portnr);   
    
  return true;

这是我的初始化端口页面,下午测试是写事件对象无效!!!!
???

#6


呵呵。。。不是有很好的已经写好的,干嘛不拿来用呀。

#7


CSerialPort有V1.19那个版本的吗,

#8


   现在有更高的版本了。

#1


线程定义成 static 型了么?

#2


1.在CSerialPort类里面 线程好像没有定义成static的
2. 为什么要定义成STATIC的了?

#3


肯定是你自己改动什么地方改错了,如果你一点不改拿过来用不可能有这个错误

#4


CSerialPort最新版
http://www.naughter.com/serialport.html
有例子,照着做就是了!

#5


BOOL CSerialPort::InitComm(CWnd* pPortOwner,
   UINT portnr,
   UINT baud,
   char parity,
   UINT databits,
   UINT stopbits,
   DWORD dwCommEvents,
   UINT writebuffersize)
{
assert(portnr>0 && portnr<5);
assert(pPortOwner!=NULL);

//if the thread is alive :kill
if(m_bThreadAlive)
{
do
{
SetEvent(m_hShutdownEvent);
}while(m_bThreadAlive);
} TRACE("Thread end!\n");

//creat events
if(m_ov.hEvent!=NULL)
ResetEvent(m_ov.hEvent);
else m_ov.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);//人工重置事件

if(m_hWriteEvent!=NULL)
{
ResetEvent(m_hWriteEvent);
}
else m_hWriteEvent=CreateEvent(NULL,TRUE,FALSE,NULL);//都是属于没有信号状态

if(m_hShutdownEvent!=NULL)
ResetEvent(m_hShutdownEvent);
else m_hShutdownEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
    
m_hEventArray[0]=m_hShutdownEvent;//highest priority
m_hEventArray[1]=m_ov.hEvent;
m_hEventArray[2]=m_hWriteEvent;

//init critical section
InitializeCriticalSection(&this->m_csCommunicationSync);
//set buffersize for writting and save the ower
m_pOwner=pPortOwner;
if(m_szWriteBuffer!=NULL)
    {
delete [] m_szWriteBuffer;
}

m_szWriteBuffer=new char[writebuffersize];
m_nPortNr=portnr;
m_nWriteBufferSize=writebuffersize;
m_dwCommEvents=dwCommEvents;
BOOL bResult=false;
char *szPort=new char[50];
char *szBaud=new char[50];

EnterCriticalSection(&this->m_csCommunicationSync);
//进入临界区
//   if   the   port   is   already   opened:   close   it   
    if(m_hComm!=NULL)
{
CloseHandle(m_hComm);
m_hComm=NULL;
}
//   prepare   port   strings   
     sprintf(szPort,"COM%d",portnr);
 sprintf(szBaud,"baud=%d parity=%c data=%d stop=%d",baud,parity,databits,stopbits);

 
  //   get   a   handle   to   the   port  
  m_hComm=CreateFile(szPort,GENERIC_READ|GENERIC_WRITE,
  0,//端口只能独享
  NULL,//默认的安全属性
  OPEN_EXISTING,
  FILE_FLAG_OVERLAPPED,
  0);//template must be 0 for comm devices


  if(m_hComm==INVALID_HANDLE_VALUE)
  {
  delete [] szPort;
  delete [] szBaud;
  return false;
  }
  if(!SetupComm(m_hComm,1024,512))
  {
         AfxMessageBox("设置缓冲区失败");
 return false;
  }
   PurgeComm(m_hComm,PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);

  //set timeout values
  m_CommTimeouts.ReadIntervalTimeout=MAXDWORD;   
  m_CommTimeouts.ReadTotalTimeoutMultiplier=0;   
  m_CommTimeouts.ReadTotalTimeoutConstant  = 0;   
  m_CommTimeouts.WriteTotalTimeoutMultiplier = 0;   
  m_CommTimeouts.WriteTotalTimeoutConstant=5000; 
  

  if(SetCommTimeouts(m_hComm,&m_CommTimeouts))
  {
  if(SetCommMask(m_hComm,dwCommEvents))
  {
  if(GetCommState(m_hComm,&m_dcb))
  {
             m_dcb.fDtrControl=RTS_CONTROL_ENABLE;//   set   RTS   bit   high! 
 m_dcb.fBinary=true;
 m_dcb.EofChar=0x1a;
 m_dcb.DCBlength=sizeof(DCB);
 m_dcb.fInX=true;
         m_dcb.fOutX=true;
         m_dcb.XoffChar=XOFF;
         m_dcb.XonChar=XON;
         m_dcb.XoffLim=256;
         m_dcb.XonLim=256;
 if(BuildCommDCB(szBaud,&m_dcb))
 {
 if(SetCommState(m_hComm,&m_dcb));
 else
 ProcessErrorMessage("SetCommState");
 }
 else ProcessErrorMessage("BuildCommDCB");

  }
  else ProcessErrorMessage("GetCommState()");
  }
  else ProcessErrorMessage("SetCommMask()");
  }
  else ProcessErrorMessage("SetCommTimeouts()");
 
  delete [] szPort;
  delete [] szBaud;
    
  LeaveCriticalSection(&m_csCommunicationSync);   
  TRACE("Initialisation   for   communicationport   %d completed.\nUse   Startmonitor   to   communicate.\n",   portnr);   
    
  return true;

这是我的初始化端口页面,下午测试是写事件对象无效!!!!
???

#6


呵呵。。。不是有很好的已经写好的,干嘛不拿来用呀。

#7


CSerialPort有V1.19那个版本的吗,

#8


   现在有更高的版本了。