一直没搞明白串口的同步和异步操作有什么区别

时间:2021-12-14 23:50:44
同步时ReadFile会死等,但是异步的WaitForSingleObject不也会造成死等,这两种操作如果放在同一线程中有何区别呢?

34 个解决方案

#1


所谓同步就是等读写操作完了才返回,异步就是一调用马上返回,会有专门的线程进行读写操作,读写完了会通知的。

#2


呵呵,其实你得理解操作系统,线程的概念,同步,一直等,直到时间片过去,而异步呢,你readfile后,后面肯定用waitforsigle,而这个命令时一点到达这个命令,如果阻塞,理解跳到其他线程,所以节省了时间

#3


换种解释方法,楼主理解SendMessage和PostMessage么?这个有异曲同工之妙。

#4


引用 3 楼 tiger9991 的回复:
换种解释方法,楼主理解SendMessage和PostMessage么?这个有异曲同工之妙。


不一样。如果异步读,不用Wait,那就跟你说的一样了,因为有个Wait,所以导致跟SendMessage一样。如果你在post后加一个等待,等待被post的窗口处理。那他跟Send有何区别?只是Send不放消息队列罢了。但是执行上都会等待

#5


引用 2 楼 herostarone 的回复:
呵呵,其实你得理解操作系统,线程的概念,同步,一直等,直到时间片过去,而异步呢,你readfile后,后面肯定用waitforsigle,而这个命令时一点到达这个命令,如果阻塞,理解跳到其他线程,所以节省了时间


windows下时间片是20ms,仅仅是异步会尽快将线程挂起?这跟同步没有太大区别吧。同步就算把时间片耗完也无所谓,如果是数据量非常大,反而要用同步,数据量不大,为这20ms似乎没太大必要。

#6


引用 1 楼 wltg2001 的回复:
所谓同步就是等读写操作完了才返回,异步就是一调用马上返回,会有专门的线程进行读写操作,读写完了会通知的。


ReadFile后的Wait,再开线程读?不会吧

#7


一个会等待完成,一个不会

#8


引用 4 楼 citroen_kimi 的回复:
引用 3 楼 tiger9991 的回复:

换种解释方法,楼主理解SendMessage和PostMessage么?这个有异曲同工之妙。


不一样。如果异步读,不用Wait,那就跟你说的一样了,因为有个Wait,所以导致跟SendMessage一样。如果你在post后加一个等待,等待被post的窗口处理。那他跟Send有何区别?只是Send不放消息队列罢了。但是执行上都会等待


PostMessage不等(异步)(进队列),SendMessage等(同步)(不进队列)。。。。你的解释感觉你把wait搞在一起思路很混乱啊

#9


楼上的,不是我搞混,是你没明白吧,Post不等没错,假如这样:设全局变量int g_n = 1,如果post前变量等于1,post给某窗口处理,这个处理会将g_n置为0,主动post的然后等待g_n变为0,这时跟Send原理虽不同,但是效果几乎相同。你认为呢?

#10


异步必然有个wait,如果你用死循环来判断那异步失去意义了,但是加上这个wait ,我认为也几乎相当于同步了。

#11


引用 6 楼 citroen_kimi 的回复:
引用 1 楼 wltg2001 的回复:

所谓同步就是等读写操作完了才返回,异步就是一调用马上返回,会有专门的线程进行读写操作,读写完了会通知的。


ReadFile后的Wait,再开线程读?不会吧

难道是我没有说清楚吗?
同步即是要等到读写工作完成之后ReadFile函数才能返回。
异步则是一调用ReadFile函数之后产即返回,由系统开线程进行读写工作,当读写工作完成之后通知调用ReadFile的线程或是调用相关的回调函数。

#12


楼上的,是不是ReadFile的线程就得一直在等待通知呢?那不就相当于阻塞在这了?

#13


就是那个WaitForSingleObject在等待,那不就是阻塞了吗?

#14


引用 12 楼 citroen_kimi 的回复:
楼上的,是不是ReadFile的线程就得一直在等待通知呢?那不就相当于阻塞在这了?

同步状态下时ReadFile这个函数只有等到读完之后才会返回,这就相当于阻塞了。
异步状态下不是,我上面说的通知有点问题,对于ReadFileEx来说,当读写工作完成之后,会自动调用
BOOL ReadFileEx(
  HANDLE hFile,
  LPVOID lpBuffer,
  DWORD nNumberOfBytesToRead,
  LPOVERLAPPED lpOverlapped,
  LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
中由第五个参数指定的回调函数。我上面所说的通知是不正确的。

#15


如果像你上面所说的,那确实是同步和异步的差别,但是看到大部分没有用这种,而且用wait,所以我认为用wait跟同步没有什么区别

#16


不明白为什么网上大部分例子异步的都是用wait来等待

#17


引用 15 楼 citroen_kimi 的回复:
如果像你上面所说的,那确实是同步和异步的差别,但是看到大部分没有用这种,而且用wait,所以我认为用wait跟同步没有什么区别

我看到的异步例子都是用ReadFileEx来完成的。根本就不用Wait啊,如果要Wait的话,那就不是异步了。所谓的异步就是让主线程不用等待读写工作,如果要等待的话,异步就没有价值了。

#18


不是吧,我看到的基本是Wait,VCKBASE上有

#19


引用 18 楼 citroen_kimi 的回复:
不是吧,我看到的基本是Wait,VCKBASE上有

刚才看了一下,确实有用ReadFile加WaitFor...函数配合来完成异步读写的。不过这也没有什么问题啊,异步读写调用ReadFile时也是一调用即返回,至于要用WaitF...函数等待那是逻辑上的需求。
我个人感觉用回调函数应该更合理一些。

#20


如果你只强调在一个线程中使用的效果
那一样
就像用菜刀砍死一个人和用原子弹炸死一个人
从杀死一个人的角度
菜刀和原子弹没有区别

#21


引用 19 楼 wltg2001 的回复:
引用 18 楼 citroen_kimi 的回复:
不是吧,我看到的基本是Wait,VCKBASE上有

刚才看了一下,确实有用ReadFile加WaitFor...函数配合来完成异步读写的。不过这也没有什么问题啊,异步读写调用ReadFile时也是一调用即返回,至于要用WaitF...函数等待那是逻辑上的需求。
我个人感觉用回调函数应该更合理一些。


我认为应该也是这样才对,可似乎网上资料都是wait,真是奇怪,难道大家用异步都是这样用不觉得有问题

#22


引用 20 楼 xianglitian 的回复:
如果你只强调在一个线程中使用的效果
那一样
就像用菜刀砍死一个人和用原子弹炸死一个人
从杀死一个人的角度
菜刀和原子弹没有区别


你可以举个在多个线程中ReadFile然后wait的例子,看是否这样比同步好,我认为你Wait后再开个线程,也是多此一举,降低效率

#23


提到效率我还真没有测试过
不过我的意思是说同步和异步操作的真正区别是在硬件的中断方式上
不过关于这一点windows做了封装

#24


引用 22 楼 citroen_kimi 的回复:
引用 20 楼 xianglitian 的回复:

如果你只强调在一个线程中使用的效果
那一样
就像用菜刀砍死一个人和用原子弹炸死一个人
从杀死一个人的角度
菜刀和原子弹没有区别


你可以举个在多个线程中ReadFile然后wait的例子,看是否这样比同步好,我认为你Wait后再开个线程,也是多此一举,降低效率

同步与异步的区别上面已经说得很清楚了,至于用不用wait那是程序逻辑上的问题,打个比方,在异步方式下,你可以在ReadFile之后不马上去Wait..,而是先去执行别的代码,然后去等待也行啊。

#25


同步: 窗体A Sendmessage To 窗体B

异步:窗体A Postmessage To 窗体B 
     窗体B 收到消息后,Sendmessage To 窗体A
     窗体A响应消息函数 

异步方式下,窗体A Postmessage 之后,和响应B发来消息之间的时间段,可以做任何其它事,并非一直等待    


串口的异步操作过程和以上过程类似,,,应该是异步的效率好些,除非你的软件只做收发串口数据这一件事

#26


引用 24 楼 wltg2001 的回复:
引用 22 楼 citroen_kimi 的回复:
引用 20 楼 xianglitian 的回复:

如果你只强调在一个线程中使用的效果
那一样
就像用菜刀砍死一个人和用原子弹炸死一个人
从杀死一个人的角度
菜刀和原子弹没有区别


你可以举个在多个线程中ReadFile然后wait的例子,看是否这样比同步好,我认为你Wait后再开个线程,也是多此一举,降低效率

同步……


不管你任何时候去等待,你还是会造成死等这种局面啊,你延后等待可能还是会没有数据,还是在那等着。我想异步的原来意图肯定不是你说的这种情况,也许设回调是唯一正确的做法

#27


引用 25 楼 delphigis 的回复:
同步: 窗体A Sendmessage To 窗体B

异步:窗体A Postmessage To 窗体B 
     窗体B 收到消息后,Sendmessage To 窗体A
     窗体A响应消息函数 

异步方式下,窗体A Postmessage 之后,和响应B发来消息之间的时间段,可以做任何其它事,并非一直等待    


串口的异步操作过程和以上过程类似,,,应该是……


严重不同意你的看法,在数据量大(比如下位机主动不间断的往上位机发送大量字节流)你用异步的效率低于同步

#28


引用 25 楼 delphigis 的回复:
同步: 窗体A Sendmessage To 窗体B

异步:窗体A Postmessage To 窗体B 
     窗体B 收到消息后,Sendmessage To 窗体A
     窗体A响应消息函数 

异步方式下,窗体A Postmessage 之后,和响应B发来消息之间的时间段,可以做任何其它事,并非一直等待    


串口的异步操作过程和以上过程类似,,,应该是……


在串口通讯处理这种功能上,你ReadFile还要去做其他事再去wait取数据,虽然有这种需求,但大部分是需要ReadFile后去解析然后进行下一步动作,没有数据何来解析?

#29


异步的好处很多,当系统出现异常时,异步方式会更好的控制局面



响应消息1    //来数据了

ReadFile -> 处理数据(存盘,转发........)

响应消息2

消息1和消息2相差time1
处理数据平均需要time2

如果time1>time2,怎么写都可以
如果time1<time2 使用异步方式很有必要





#30


引用 29 楼 delphigis 的回复:
异步的好处很多,当系统出现异常时,异步方式会更好的控制局面



响应消息1    //来数据了

ReadFile -> 处理数据(存盘,转发........)

响应消息2

消息1和消息2相差time1
处理数据平均需要time2

如果time1>time2,怎么写都可以
如果time1<time2 使用异步方式很有必要


不排除有这可能,但如果你用了time1<time2,你确定能保证time1<time2吗,我想很少有人用这个的同时心里很有把握。

#31


这帖子到最后都快成剧场版了

#32


并不是用了time1<time2,,,,处理数据的时间只有你自己知道啊

如果个别数据处理很费时,你就必须采用异步方式 ,并且要新开个线程,新建buf来处理数据,这样才能一边接收一边处理

如果处理数据的时间相对于接收时间间隔来说可以忽略不计,直接处理就行了


#33


引用 31 楼 tiger9991 的回复:
这帖子到最后都快成剧场版了


既然有星了,说话希望是有建设性的,不是这种无谓的废话

#34


引用 32 楼 delphigis 的回复:
并不是用了time1<time2,,,,处理数据的时间只有你自己知道啊

如果个别数据处理很费时,你就必须采用异步方式 ,并且要新开个线程,新建buf来处理数据,这样才能一边接收一边处理

如果处理数据的时间相对于接收时间间隔来说可以忽略不计,直接处理就行了


我经常这样使用,开一线程同步ReadFile,读取到后放在某个缓冲区,另开线程解析(前提是通讯协议加帧头和帧尾),但是遇到应答方式通讯的协议的话,这种处理应该不是很合理,但如果同一线程中用异步WaitForSingleObject似乎跟同步区别不大。用回调肯定是个好办法

#1


所谓同步就是等读写操作完了才返回,异步就是一调用马上返回,会有专门的线程进行读写操作,读写完了会通知的。

#2


呵呵,其实你得理解操作系统,线程的概念,同步,一直等,直到时间片过去,而异步呢,你readfile后,后面肯定用waitforsigle,而这个命令时一点到达这个命令,如果阻塞,理解跳到其他线程,所以节省了时间

#3


换种解释方法,楼主理解SendMessage和PostMessage么?这个有异曲同工之妙。

#4


引用 3 楼 tiger9991 的回复:
换种解释方法,楼主理解SendMessage和PostMessage么?这个有异曲同工之妙。


不一样。如果异步读,不用Wait,那就跟你说的一样了,因为有个Wait,所以导致跟SendMessage一样。如果你在post后加一个等待,等待被post的窗口处理。那他跟Send有何区别?只是Send不放消息队列罢了。但是执行上都会等待

#5


引用 2 楼 herostarone 的回复:
呵呵,其实你得理解操作系统,线程的概念,同步,一直等,直到时间片过去,而异步呢,你readfile后,后面肯定用waitforsigle,而这个命令时一点到达这个命令,如果阻塞,理解跳到其他线程,所以节省了时间


windows下时间片是20ms,仅仅是异步会尽快将线程挂起?这跟同步没有太大区别吧。同步就算把时间片耗完也无所谓,如果是数据量非常大,反而要用同步,数据量不大,为这20ms似乎没太大必要。

#6


引用 1 楼 wltg2001 的回复:
所谓同步就是等读写操作完了才返回,异步就是一调用马上返回,会有专门的线程进行读写操作,读写完了会通知的。


ReadFile后的Wait,再开线程读?不会吧

#7


一个会等待完成,一个不会

#8


引用 4 楼 citroen_kimi 的回复:
引用 3 楼 tiger9991 的回复:

换种解释方法,楼主理解SendMessage和PostMessage么?这个有异曲同工之妙。


不一样。如果异步读,不用Wait,那就跟你说的一样了,因为有个Wait,所以导致跟SendMessage一样。如果你在post后加一个等待,等待被post的窗口处理。那他跟Send有何区别?只是Send不放消息队列罢了。但是执行上都会等待


PostMessage不等(异步)(进队列),SendMessage等(同步)(不进队列)。。。。你的解释感觉你把wait搞在一起思路很混乱啊

#9


楼上的,不是我搞混,是你没明白吧,Post不等没错,假如这样:设全局变量int g_n = 1,如果post前变量等于1,post给某窗口处理,这个处理会将g_n置为0,主动post的然后等待g_n变为0,这时跟Send原理虽不同,但是效果几乎相同。你认为呢?

#10


异步必然有个wait,如果你用死循环来判断那异步失去意义了,但是加上这个wait ,我认为也几乎相当于同步了。

#11


引用 6 楼 citroen_kimi 的回复:
引用 1 楼 wltg2001 的回复:

所谓同步就是等读写操作完了才返回,异步就是一调用马上返回,会有专门的线程进行读写操作,读写完了会通知的。


ReadFile后的Wait,再开线程读?不会吧

难道是我没有说清楚吗?
同步即是要等到读写工作完成之后ReadFile函数才能返回。
异步则是一调用ReadFile函数之后产即返回,由系统开线程进行读写工作,当读写工作完成之后通知调用ReadFile的线程或是调用相关的回调函数。

#12


楼上的,是不是ReadFile的线程就得一直在等待通知呢?那不就相当于阻塞在这了?

#13


就是那个WaitForSingleObject在等待,那不就是阻塞了吗?

#14


引用 12 楼 citroen_kimi 的回复:
楼上的,是不是ReadFile的线程就得一直在等待通知呢?那不就相当于阻塞在这了?

同步状态下时ReadFile这个函数只有等到读完之后才会返回,这就相当于阻塞了。
异步状态下不是,我上面说的通知有点问题,对于ReadFileEx来说,当读写工作完成之后,会自动调用
BOOL ReadFileEx(
  HANDLE hFile,
  LPVOID lpBuffer,
  DWORD nNumberOfBytesToRead,
  LPOVERLAPPED lpOverlapped,
  LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
中由第五个参数指定的回调函数。我上面所说的通知是不正确的。

#15


如果像你上面所说的,那确实是同步和异步的差别,但是看到大部分没有用这种,而且用wait,所以我认为用wait跟同步没有什么区别

#16


不明白为什么网上大部分例子异步的都是用wait来等待

#17


引用 15 楼 citroen_kimi 的回复:
如果像你上面所说的,那确实是同步和异步的差别,但是看到大部分没有用这种,而且用wait,所以我认为用wait跟同步没有什么区别

我看到的异步例子都是用ReadFileEx来完成的。根本就不用Wait啊,如果要Wait的话,那就不是异步了。所谓的异步就是让主线程不用等待读写工作,如果要等待的话,异步就没有价值了。

#18


不是吧,我看到的基本是Wait,VCKBASE上有

#19


引用 18 楼 citroen_kimi 的回复:
不是吧,我看到的基本是Wait,VCKBASE上有

刚才看了一下,确实有用ReadFile加WaitFor...函数配合来完成异步读写的。不过这也没有什么问题啊,异步读写调用ReadFile时也是一调用即返回,至于要用WaitF...函数等待那是逻辑上的需求。
我个人感觉用回调函数应该更合理一些。

#20


如果你只强调在一个线程中使用的效果
那一样
就像用菜刀砍死一个人和用原子弹炸死一个人
从杀死一个人的角度
菜刀和原子弹没有区别

#21


引用 19 楼 wltg2001 的回复:
引用 18 楼 citroen_kimi 的回复:
不是吧,我看到的基本是Wait,VCKBASE上有

刚才看了一下,确实有用ReadFile加WaitFor...函数配合来完成异步读写的。不过这也没有什么问题啊,异步读写调用ReadFile时也是一调用即返回,至于要用WaitF...函数等待那是逻辑上的需求。
我个人感觉用回调函数应该更合理一些。


我认为应该也是这样才对,可似乎网上资料都是wait,真是奇怪,难道大家用异步都是这样用不觉得有问题

#22


引用 20 楼 xianglitian 的回复:
如果你只强调在一个线程中使用的效果
那一样
就像用菜刀砍死一个人和用原子弹炸死一个人
从杀死一个人的角度
菜刀和原子弹没有区别


你可以举个在多个线程中ReadFile然后wait的例子,看是否这样比同步好,我认为你Wait后再开个线程,也是多此一举,降低效率

#23


提到效率我还真没有测试过
不过我的意思是说同步和异步操作的真正区别是在硬件的中断方式上
不过关于这一点windows做了封装

#24


引用 22 楼 citroen_kimi 的回复:
引用 20 楼 xianglitian 的回复:

如果你只强调在一个线程中使用的效果
那一样
就像用菜刀砍死一个人和用原子弹炸死一个人
从杀死一个人的角度
菜刀和原子弹没有区别


你可以举个在多个线程中ReadFile然后wait的例子,看是否这样比同步好,我认为你Wait后再开个线程,也是多此一举,降低效率

同步与异步的区别上面已经说得很清楚了,至于用不用wait那是程序逻辑上的问题,打个比方,在异步方式下,你可以在ReadFile之后不马上去Wait..,而是先去执行别的代码,然后去等待也行啊。

#25


同步: 窗体A Sendmessage To 窗体B

异步:窗体A Postmessage To 窗体B 
     窗体B 收到消息后,Sendmessage To 窗体A
     窗体A响应消息函数 

异步方式下,窗体A Postmessage 之后,和响应B发来消息之间的时间段,可以做任何其它事,并非一直等待    


串口的异步操作过程和以上过程类似,,,应该是异步的效率好些,除非你的软件只做收发串口数据这一件事

#26


引用 24 楼 wltg2001 的回复:
引用 22 楼 citroen_kimi 的回复:
引用 20 楼 xianglitian 的回复:

如果你只强调在一个线程中使用的效果
那一样
就像用菜刀砍死一个人和用原子弹炸死一个人
从杀死一个人的角度
菜刀和原子弹没有区别


你可以举个在多个线程中ReadFile然后wait的例子,看是否这样比同步好,我认为你Wait后再开个线程,也是多此一举,降低效率

同步……


不管你任何时候去等待,你还是会造成死等这种局面啊,你延后等待可能还是会没有数据,还是在那等着。我想异步的原来意图肯定不是你说的这种情况,也许设回调是唯一正确的做法

#27


引用 25 楼 delphigis 的回复:
同步: 窗体A Sendmessage To 窗体B

异步:窗体A Postmessage To 窗体B 
     窗体B 收到消息后,Sendmessage To 窗体A
     窗体A响应消息函数 

异步方式下,窗体A Postmessage 之后,和响应B发来消息之间的时间段,可以做任何其它事,并非一直等待    


串口的异步操作过程和以上过程类似,,,应该是……


严重不同意你的看法,在数据量大(比如下位机主动不间断的往上位机发送大量字节流)你用异步的效率低于同步

#28


引用 25 楼 delphigis 的回复:
同步: 窗体A Sendmessage To 窗体B

异步:窗体A Postmessage To 窗体B 
     窗体B 收到消息后,Sendmessage To 窗体A
     窗体A响应消息函数 

异步方式下,窗体A Postmessage 之后,和响应B发来消息之间的时间段,可以做任何其它事,并非一直等待    


串口的异步操作过程和以上过程类似,,,应该是……


在串口通讯处理这种功能上,你ReadFile还要去做其他事再去wait取数据,虽然有这种需求,但大部分是需要ReadFile后去解析然后进行下一步动作,没有数据何来解析?

#29


异步的好处很多,当系统出现异常时,异步方式会更好的控制局面



响应消息1    //来数据了

ReadFile -> 处理数据(存盘,转发........)

响应消息2

消息1和消息2相差time1
处理数据平均需要time2

如果time1>time2,怎么写都可以
如果time1<time2 使用异步方式很有必要





#30


引用 29 楼 delphigis 的回复:
异步的好处很多,当系统出现异常时,异步方式会更好的控制局面



响应消息1    //来数据了

ReadFile -> 处理数据(存盘,转发........)

响应消息2

消息1和消息2相差time1
处理数据平均需要time2

如果time1>time2,怎么写都可以
如果time1<time2 使用异步方式很有必要


不排除有这可能,但如果你用了time1<time2,你确定能保证time1<time2吗,我想很少有人用这个的同时心里很有把握。

#31


这帖子到最后都快成剧场版了

#32


并不是用了time1<time2,,,,处理数据的时间只有你自己知道啊

如果个别数据处理很费时,你就必须采用异步方式 ,并且要新开个线程,新建buf来处理数据,这样才能一边接收一边处理

如果处理数据的时间相对于接收时间间隔来说可以忽略不计,直接处理就行了


#33


引用 31 楼 tiger9991 的回复:
这帖子到最后都快成剧场版了


既然有星了,说话希望是有建设性的,不是这种无谓的废话

#34


引用 32 楼 delphigis 的回复:
并不是用了time1<time2,,,,处理数据的时间只有你自己知道啊

如果个别数据处理很费时,你就必须采用异步方式 ,并且要新开个线程,新建buf来处理数据,这样才能一边接收一边处理

如果处理数据的时间相对于接收时间间隔来说可以忽略不计,直接处理就行了


我经常这样使用,开一线程同步ReadFile,读取到后放在某个缓冲区,另开线程解析(前提是通讯协议加帧头和帧尾),但是遇到应答方式通讯的协议的话,这种处理应该不是很合理,但如果同一线程中用异步WaitForSingleObject似乎跟同步区别不大。用回调肯定是个好办法