婚礼策划网 加入收藏  -  设为首页
您的位置:婚礼策划网 > 知识百科 > 正文
VC 调用WaitforSingleObject报错.该怎么处理
VC 调用WaitforSingleObject报错.该怎么处理
提示:

VC 调用WaitforSingleObject报错.该怎么处理

////////参考:C/C++ code///////////////////////////////////////////////////////
int CUload::ReadCommBlock(BYTE *pBlock,int nBlockLen)
{ //return 0 if error
int WaitErr;
BOOL fReadStart;
COMSTAT ComStat;
DWORD dwErrorFlags,dwLength;
if (!m_bConnected) return 0;
if (ClearCommError(m_idComDev,&dwErrorFlags,&ComStat))
{ //ComStat filled
if (dwErrorFlags)
{
if (dwErrorFlags & CE_RXOVER) AfxMessageBox("Receive Queue overflow");
else if(dwErrorFlags & CE_OVERRUN) AfxMessageBox("Receive Overrun Error");
else if(dwErrorFlags & CE_RXPARITY) AfxMessageBox("Receive Parity Error");
else if(dwErrorFlags & CE_FRAME ) AfxMessageBox("Receive Framing error");
else if(dwErrorFlags & CE_BREAK) AfxMessageBox("Break Detected");
else AfxMessageBox("CE_OTHERS");
}
}
// nBlockLen may >,=,< ComStat.cbInQue !
dwLength=min((DWORD)nBlockLen,ComStat.cbInQue);
if(dwLength>0)
{ // read required
fReadStart=ReadFile(m_idComDev,pBlock,dwLength,&dwLength,&m_osRead);
if(!fReadStart)
{ // if there was a problem, or the async. operation's still pending ...
if(GetLastError()==ERROR_IO_PENDING)
{ // asynchronous i/o is still in progress
if (WaitErr=WaitForSingleObject(m_osRead.hEvent,60000))// 1 minute
{ // time over
if(WaitErr==WAIT_TIMEOUT)
{ // time out
dwLength=0;
AfxMessageBox("Time out !");
}// end time out
}// end waiterr
} // end io_pending
else
{ // WaitErr=0.if you SetEvent(m_osRead.hEvent) anywhere else
GetOverlappedResult(m_idComDev,&m_osRead,&dwLength,FALSE);
m_osRead.Offset +=dwLength;
}
}
} //end if dwLength>0
return dwLength;
}
// an work thread to monitor the _CTS and RX_CHAR
UINT CUload::CommWatchRead(LPVOID lpParam)
{ // return 0=OK 1=Error
CUload *pUload=(CUload*)lpParam;
OVERLAPPED os;
DWORD dwEventMask,dwTransfer;
memset(&os,0,sizeof(OVERLAPPED));
os.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);// attrb,Manual,init,name
if (os.hEvent==NULL)
{
AfxMessageBox("Can't create Event",MB_ICONSTOP);
return 1;// error
}
// set 2 events !
if (!SetCommMask(pUload->m_idComDev,EV_RXCHAR|EV_CTS)) return 1;
while (pUload->m_bConnected)
{ // break,only if m_bConnected=NULL
dwEventMask=0;
if(!WaitCommEvent(pUload->m_idComDev,&dwEventMask,&os))
{ // function fails
if (GetLastError()==ERROR_IO_PENDING)
{// TRUE=WaitForSingleObject() should be called inside
GetOverlappedResult(pUload->m_idComDev,&os,&dwTransfer,TRUE);
os.Offset+=dwTransfer;
}
}
if((dwEventMask & EV_RXCHAR)==EV_RXCHAR)
{ // some chats received.
ResetEvent(pUload->m_hPostEventRead);// first reset
pUload->PostMessage(WM_COMMNOTIFY,
(WPARAM)1, // EV_RXCHAR
(LPARAM)0); // not used
// wait answer
WaitForSingleObject(pUload->m_hPostEventRead,0xFFFFFFFF);
}
// if not at same time,use else if
if((dwEventMask & EV_CTS)==EV_CTS)
{ // CTS changed
ResetEvent(pUload->m_hPostEventRead);// first reset
pUload->PostMessage(WM_COMMNOTIFY,
(WPARAM)0, // EV_CTS
(LPARAM)0); // not used
// wait answer
WaitForSingleObject(pUload->m_hPostEventRead,0xFFFFFFFF);
}
}
CloseHandle(os.hEvent);
return 0;// OK
}

如何学习和使用 waitforsingleobject
提示:

如何学习和使用 waitforsingleobject

用最简单的语言说就是这个对象有两个状态比如我们称0和1,称什么一点也不重要,有信号和无信号就是相对的两个状态,没什么意义,你就认为一个状态是0另一个状态是1。
在程序里如果加了WaitForSingleObject,那么程序到这里就去检测你给他的那个句柄的状态,如果是0程序就停在这里了,如果是1,程序就继续下去。

那么线程同步就要利用这两个状态。假如你有两个线程,都有可能访问同一个文件,而同一个文件是不能被两个线程同时写入的,那么你就需要在写入之前先判断文件有没有被另一个线程在写入,如果有则等着,等另一个线程写完之后你再继续,我们不能用一个死循坏来尝试打开文件知道成功为止,这样会让CPU有非常高的占用率。
这里你就要创建一个对象,这个对象有两个状态,我们约定,如果一个线程要写入文件之前就把这个对象状态变成0,写完之后把它变回1,那么另一个线程在写文件之前只要检测这个对象是不是为0就可以确定文件有没有被另一个线程在写入了。检测的过程就用WaitForSingleObject来操作,如果为1,WaitForSingleObject就和没这句话一样立刻执行下去了,如果那个对象是个0,那么WaitForSingleObject就会停在这里等,等到另一个线程写完文件,因为那个线程在写完文件之后会把对象变成1。
这个状态1我们命名为有信号状态,状态0我们称无信号状态。我们就把这个对象叫做互斥体,他起到了对这个文件读写的互斥作用。这整个写文件之前之后改变互斥体状态,写之前检测互斥体状态这个过程就是一个线程的同步。
同步是编程的人自己要考虑的问题,系统不会帮你同步,也就是说我们进行了上述的约定之后,你在编程的时候必须要在写入文件之前将互斥体置为无信号状态,写完之后置为有信号状态。
这样应该好懂了吧?不懂继续追问吧。