异步的局限性

combobox2013 2013-07-19 04:28:05
我只调用一次read函数,且用在主线程中, 需要知道readfile的成功与否,这里用用异步?能行吗?

感觉不行,异步似乎只能够用在反复的调用read函数的情形下,如果你只用一次read函数,那么以下的设计是不对的!!!



read函数伪代码为:
{


COMSTAT ComStat;
DWORD dwErrorFlag;

DWORD dwCurrentWritten = 0;
DWORD dwLastWitten = 0;
BOOL bRet;
if (m_bSendPending)
{
bRet = GetOverlappedResult(m_hPort, &SendOverLapped, &dwLastWitten, FALSE);
if(bRet)
{
m_bSendPending = FALSE;
}
else
{
if (GetLastError() == ERROR_IO_INCOMPLETE)
return 0;
else
{
bRet = ClearCommError(m_hPort, &dwErrorFlag, &ComStat);
m_bSendPending = FALSE;
}
}
}

if (m_bSendPending == FALSE)
{
bRet = WriteFile(m_hPort, szBuffer, iExpectCount, &dwCurrentWritten, &SendOverLapped); //读字节写入缓存
if (bRet == FALSE)
{
if (GetLastError() == ERROR_IO_PENDING)
m_bSendPending = TRUE;
else
{
bRet = ClearCommError(m_hPort, &dwErrorFlag, &ComStat);
}
}


}




因为用户需要知道是否写入串口成功否?这里采用异步就是不对的,是否去掉异步,改成同步?



...全文
250 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
combobox2013 2013-07-23
  • 打赏
  • 举报
回复
引用 10 楼 lijianli9 的回复:
threadproc while(pSerialPort->m_bOpened) { ClearCommError(pSerialPort->m_hCom, &dwErrorFlags, &ComStat); if(ComStat.cbInQue) { WaitForSingleObject(pSerialPort->m_hCanReadEvent, INFINITE); ResetEvent(pSerialPort->m_hCanReadEvent); pSerialPort->RecvChar(); continue; } } recvchar /********************************************************************/ /** 功能: 读取字符 */ /** 参数: 无 */ /** TRUE--成功 */ /** FALSE--失败 */ /********************************************************************/ BOOL CSerialPortEx::RecvChar() { if(!m_bInitComOk) { return FALSE; } char cCh; int nLength; if(!m_bOpened) { //允许读取下一个数据 SetEvent(m_hCanReadEvent); return FALSE; } nLength = ReadCom(&cCh, 1); EnterCriticalSection(&m_csComSync); m_CharList.AddTail(cCh); if(m_CharList.GetCount() > 2048) { m_CharList.RemoveHead(); } LeaveCriticalSection(&m_csComSync); SetEvent(m_hCanReadEvent); return TRUE; } 线程函数中,获取串口队列中的数据,然后压入队列。应用层从队列中获取。
晕,搞了太复杂了

同一个线程 写--读--写--读

我写了一个命令,就要得到其结果,过了会,我再写,再得到结果,这是需求。

为啥放在主线程中呢? 主线程中有定时器,这个定时器的功能,可以对获得的数据发送给网络。


所以就放定时器中了。

此时有2个选择:

1.直接用readfile ,writefile,createfile等函数, createfile 的参数别用 重叠结构。

这种效率不好。那么需要改进。

参考你的和网络的文章,有了 2

2. 利用重叠结构体, 写用一个结构体,读也用一个结构体。

无论是读还是写,我都没有createevent一个句柄给重叠结构的m_hEvent赋值。

因为我直接用getoverlappedresult去查询系统缓冲区的状态, 让这个函数去等待,而
不是让 writefile去等待。


对于第2种,我窃以为 这种伪异步比 真正的同步稍微好一点。







向立天 2013-07-22
  • 打赏
  • 举报
回复
我也不是特别喜欢用异步通信 只要不是严重阻塞主线程都是同步操作
combobox2013 2013-07-22
  • 打赏
  • 举报
回复
引用 7 楼 lijianli9 的回复:
read 那个重贴结构为空,你的线程就阻塞在哪里了,不能进行其他操作了,应该是前者比较高。
多谢思路,不过我的有点不同, 我是 主线程里处理一写一读, 写发送命令,然后立即读取,读取解析。 所以对读取来说,不要加锁。 而且我也没有理解你的读操作的思路,可否再点拨一下,多谢
lijianli9 2013-07-22
  • 打赏
  • 举报
回复
threadproc while(pSerialPort->m_bOpened) { ClearCommError(pSerialPort->m_hCom, &dwErrorFlags, &ComStat); if(ComStat.cbInQue) { WaitForSingleObject(pSerialPort->m_hCanReadEvent, INFINITE); ResetEvent(pSerialPort->m_hCanReadEvent); pSerialPort->RecvChar(); continue; } } recvchar /********************************************************************/ /** 功能: 读取字符 */ /** 参数: 无 */ /** TRUE--成功 */ /** FALSE--失败 */ /********************************************************************/ BOOL CSerialPortEx::RecvChar() { if(!m_bInitComOk) { return FALSE; } char cCh; int nLength; if(!m_bOpened) { //允许读取下一个数据 SetEvent(m_hCanReadEvent); return FALSE; } nLength = ReadCom(&cCh, 1); EnterCriticalSection(&m_csComSync); m_CharList.AddTail(cCh); if(m_CharList.GetCount() > 2048) { m_CharList.RemoveHead(); } LeaveCriticalSection(&m_csComSync); SetEvent(m_hCanReadEvent); return TRUE; } 线程函数中,获取串口队列中的数据,然后压入队列。应用层从队列中获取。
lijianli9 2013-07-21
  • 打赏
  • 举报
回复
read 那个重贴结构为空,你的线程就阻塞在哪里了,不能进行其他操作了,应该是前者比较高。
combobox2013 2013-07-21
  • 打赏
  • 举报
回复
引用 5 楼 lijianli9 的回复:
用异步不好控制,但是性能,客户体验比较好。 你的需求如果写-读--写--读,这个可以用同步方式。 BOOL bState; DWORD dwLen = 1; COMSTAT ComStat; DWORD dwErrorFlags; ClearCommError(m_hCom, &dwErrorFlags, &ComStat); PurgeComm(m_hCom, PURGE_TXCLEAR); bState = WriteFile(m_hCom, &ch, dwLen, &dwLen, &m_osWrite); if(!bState) { if(GetLastError() == ERROR_IO_PENDING) { GetOverlappedResult(m_hCom, &m_osWrite, &dwLen, TRUE);// 等待 } else { dwLen = 0; } } if(dwLen == 1) { return TRUE; } return FALSE; read的方式,你串口操作中把读取到的数据放入到队列缓冲区中,然后read从这个队列中获取。 EnterCriticalSection(&m_csComSync); ch = m_CharList.GetHead(); m_CharList.RemoveHead(); LeaveCriticalSection(&m_csComSync);
请教一个问题,你的这种伪异步本质和 直接在readfile里对重叠结构体指针设置为null,效率一样吗? 还是前者大于后者?
lijianli9 2013-07-21
  • 打赏
  • 举报
回复
用异步不好控制,但是性能,客户体验比较好。 你的需求如果写-读--写--读,这个可以用同步方式。 BOOL bState; DWORD dwLen = 1; COMSTAT ComStat; DWORD dwErrorFlags; ClearCommError(m_hCom, &dwErrorFlags, &ComStat); PurgeComm(m_hCom, PURGE_TXCLEAR); bState = WriteFile(m_hCom, &ch, dwLen, &dwLen, &m_osWrite); if(!bState) { if(GetLastError() == ERROR_IO_PENDING) { GetOverlappedResult(m_hCom, &m_osWrite, &dwLen, TRUE);// 等待 } else { dwLen = 0; } } if(dwLen == 1) { return TRUE; } return FALSE; read的方式,你串口操作中把读取到的数据放入到队列缓冲区中,然后read从这个队列中获取。 EnterCriticalSection(&m_csComSync); ch = m_CharList.GetHead(); m_CharList.RemoveHead(); LeaveCriticalSection(&m_csComSync);
yiyefangzhou24 2013-07-20
  • 打赏
  • 举报
回复
我没玩过串口,帮你找找资料 http://bbs.csdn.net/topics/390522580?page=1#post-395080059
yiyefangzhou24 2013-07-20
  • 打赏
  • 举报
回复
我先帮你顶一下把,我也说我好像没有回过你的帖子
combobox2013 2013-07-20
  • 打赏
  • 举报
回复
大家说,我的需求如下,我改用异步,还是同步? 我有个定时操作: 首先需要往串口写数据,发送命令,然后读取串口执行命令后发回的结果。 我的需求,到底该用啥? 如果用同步,我觉得是对的, 因为异步,你没法子做到,调用一次writefile函数就可以写入成功。 所以紧接着调用readfile,很可能失败。 周而复始,我感觉只能用同步了。 但是 这2个操作,放定时器里,似乎不太好吧。
combobox2013 2013-07-19
  • 打赏
  • 举报
回复
自己up吧,等待中

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧