Windows CloseHandle()在串行端口实际关闭之前返回

Windows CloseHandle()在串行端口实际关闭之前返回,windows,winapi,serial-port,iocp,io-completion-ports,Windows,Winapi,Serial Port,Iocp,Io Completion Ports,我在绞尽脑汁想弄清楚串口何时关闭完毕,以便重新打开它。事实证明,CloseHandle()在端口实际解锁之前返回 我使用CreateFile(FILE\u FLAG\u OVERLAPPED)打开一个串行端口,使用CreateIoCompletionPort()将它与一个CompletionPort关联,使用ReadFile()读取/写入它,WriteFile()并使用CloseHandle()关闭它 我注意到,如果我足够快地关闭并重新打开串行端口,我会从CreateFile()返回一个错误\u

我在绞尽脑汁想弄清楚串口何时关闭完毕,以便重新打开它。事实证明,
CloseHandle()
在端口实际解锁之前返回

我使用
CreateFile(FILE\u FLAG\u OVERLAPPED)
打开一个串行端口,使用
CreateIoCompletionPort()
将它与一个CompletionPort关联,使用
ReadFile()
读取/写入它,
WriteFile()
并使用
CloseHandle()
关闭它

我注意到,如果我足够快地关闭并重新打开串行端口,我会从
CreateFile()
返回一个
错误\u访问被拒绝
。尽管我正在等待
CloseHandle()
返回,然后等待与该句柄相关的所有未完成读/写操作从完成端口返回,但仍会发生这种情况。当然还有更好的办法:)

如何同步关闭串行端口?请不要重试循环、sleep()或其他一些廉价的攻击


编辑:这可能与我使用的完成端口和文件重叠有关。读/写操作完成后,我会收到一个回调。端口关闭是否有某种回调?

我认为问题在于为COM端口提供服务的驱动程序。因此,不会有API“实际关闭”COM端口

顺便说一句,关闭文件句柄后,无需等待所有未完成的I/O完成并出现错误。当
CloseHandle
返回所有已完成/取消的未完成I/O时,您只需异步接收回调(无论是通过完成端口还是APC队列)

具体来说,FTDI驱动程序(模拟COM->USB的驱动程序)非常容易出错

我可能只建议在关闭句柄之前尝试刷新数据。您可以等待所有I/O完成,然后关闭COM端口(如果这适用于您的情况)。或者,您可以调用
SetCommMask
WaitCommEvent
以确保没有发送数据挂起。希望这能有所帮助

编辑:

CloseHandle
是否立即(在返回之前)取消文件句柄上所有挂起的I/O

严格地说-

可能还有其他对文件对象的引用。例如,用户模式代码可以调用
DuplicateHandle
,或者内核模式驱动程序可以调用
ObReferenceObjectByXXXX
。在这种情况下,句柄引用的对象不一定被释放

当最后一个手柄关闭时,将调用驱动程序的
DispatchCleanup
。它必须根据取消所有未完成的I/O

但是,当一个线程位于
CloseHandle
中时,理论上可以从另一个线程发出另一个I/O(如果幸运的话,句柄仍然有效)。在调用I/O函数(如
WriteFile
等)时,操作系统会临时增加对象的引用计数器。这反过来可能会启动另一个I/O,该I/O不会被
CloseHandle
调用直接取消

但是,在这种情况下,在发出新I/O后,O/S将立即关闭句柄,因为对对象的引用计数再次达到0


因此,在这种反常的情况下,可能会发生这样的情况,即在调用
CloseHandle
后,您无法再次重新打开文件。

确保在发出CloseHandle()请求(可能在其他线程上)后,读写器失败(句柄无效)在再次尝试触摸设备之前。在尝试发出另一个CreateFile之前,您可以将此作为提示来清理所有io处理。我必须说,完成端口看起来确实是不必要的巴洛克风格。

当您在线程中打开COM端口时,操作系统会打开另一个隐藏线程来执行I/O。我正在尝试解决关闭端口的问题。我能说的一种可能有效的方法是:1)挂起打开COM端口的线程,2)PurgeComm()停止所有I/O并清空所有读/写I/O缓冲区,3)然后尝试关闭COM端口。可能涉及waitforsingleobject来确定带有COM端口的线程何时实际挂起。除非COM端口绝对需要关闭,否则我正在考虑让COM端口保持打开状态,并让WinProc处理IDM_Exit命令以关闭COM端口、线程和应用程序。不是我想要的,而是我可以接受的选择。我正在使用USB到串行端口连接,不确定这会导致什么问题。我知道如果您使用的是USB到串行端口接口,则需要将针脚20设置为高(DTR)。引脚20有助于为接口供电,但仅提供约30ma的电流。如果所有这些工作,我会更新这篇文章,让你知道如果我能够关闭COM端口。Windows把串行端口驱动程序弄得一团糟,似乎满足于把事情弄得一团糟

可能与您的特定串行端口驱动程序有关。你在这里看过这个吗?所以,只是为了确定。。。。您没有在任何地方使用过
DuplicateHandle
?我不确定完成端口是否相关,我一直使用APC回调与
ReadFileEx
WriteFileEx
。这也更简单,因为APCs只在线程进入可警报等待时运行,所以没有跨线程同步问题(只是要小心重入)。我怀疑这是由不完整的I/O请求引起的。但是从根本上解决这个问题,关闭一个串行端口并重新打开它是没有意义的。事实上,这不是串行端口独有的,我不认为你做错了什么。我在文件句柄方面也遇到过同样的问题。两个时间段之间存在明显的滞后