我想检查WriteFile函数是否写入UART,以便我可以在同一个ComDev上调用ReadFile而不会导致异常。
WriteFile function似乎可以在写完之前返回。
BOOL WriteCommBlock(HANDLE * pComDev, char *pBuffer , int BytesToWrite)
{
while(fComPortInUse){}
fComPortInUse = 1;
BOOL bWriteStat = 0;
DWORD BytesWritten = 0;
COMSTAT ComStat = {0};
OVERLAPPED osWrite = {0,0,0};
if(WriteFile(*pComDev,pBuffer,BytesToWrite,&BytesWritten,&osWrite) == FALSE)
{
short Errorcode = GetLastError();
if( Errorcode != ERROR_IO_PENDING )
short breakpoint = 5; // Error
Sleep(1000); // complete write operation TBD
fComPortInUse = 0;
return (FALSE);
}
fComPortInUse = 0;
return (TRUE);
}
我使用Sleep(1000)作为解决方法,但我该如何等待适当的时间?
答案 0 :(得分:1)
您可以创建一个事件,将其存储在重叠结构中并等待它发出信号。像这样(未经测试):
BOOL WriteCommBlock(HANDLE * pComDev, char *pBuffer , int BytesToWrite)
{
while(fComPortInUse){}
fComPortInUse = 1;
BOOL bWriteStat = 0;
DWORD BytesWritten = 0;
COMSTAT ComStat = {0};
OVERLAPPED osWrite = {0,0,0};
HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (hEvent != NULL)
{
osWrite.hEvent = hEvent;
if(WriteFile(*pComDev,pBuffer,BytesToWrite,&BytesWritten,&osWrite) == FALSE)
{
short Errorcode = GetLastError();
if( Errorcode != ERROR_IO_PENDING )
short breakpoint = 5; // Error
WaitForSingleObject(hEvent, INFINITE);
fComPortInUse = 0;
return (FALSE);
}
CloseHandle(hEvent);
}
fComPortInUse = 0;
return (TRUE);
}
请注意,根据您尝试做的其他操作,只需调用WaitForSingleObject()可能不是最佳选择。并且INFINITE也不会超时。
答案 1 :(得分:1)
您的问题是错误使用重叠的I / O,无论是UART还是其他任何底层设备。
修复代码最简单(但不一定是最优化)的方法是使用事件来处理I / O完成。
// ...
OVERLAPPED osWrite = {0,0,0};
osWrite.hEvent = CreateEvent(FALSE, NULL, NULL, FALSE);
if(WriteFile(*pComDev,pBuffer,BytesToWrite,&BytesWritten,&osWrite) == FALSE)
{
DWORD Errorcode = GetLastError();
// ensure it's ERROR_IO_PENDING
WaitForSingleObject(osWrite.hEvent, INFINITE);
}
CloseHandle(osWrite.hEvent);
但请注意,整个I / O是同步的。操作系统以异步方式处理它,但是代码在完成之前不会继续运行。如果是这样,为什么还要使用重叠的I / O?
应该使用它来同时处理同一线程中的多个I / O(和其他任务)。要正确执行此操作 - 您应该在堆上分配OVERLAPPED
结构并使用其中一个可用的完成机制:事件,APC,完成端口等。您的程序流逻辑也应该更改。
答案 2 :(得分:0)
你的Sleep(1000);
没有用,它只会在writefile完成其操作后执行。你必须等到WriteFile结束。
if(WriteFile(*pComDev,pBuffer,BytesToWrite,&BytesWritten,&osWrite) == FALSE)
{}
你必须知道条件语句中的任何内容只有在结果为真时才会执行。 在这里,结果在WriteFile例程完成后(无论是完整的还是有错误的)发送到程序。
答案 3 :(得分:0)
由于您没有说您需要异步I / O,因此您应该尝试同步。这更容易。我想如果你只是为OVERLAPPED arg传递一个空指针,你会得到同步,阻塞,I / O.请参阅本文档“Windows C”部分中编写的示例代码:
答案 4 :(得分:0)
好的,我错过了读/写代码中重叠的I / O OVL参数,所以我也只是昨天作为评论回复,否则我会用downvotes敲打:(
处理重叠I / O的经典方法是将_OVL结构作为在重叠读/写调用中发出的缓冲类的数据成员。这使得同时加载读取和写入调用变得容易(或者实际上,具有单独缓冲区实例的多个读取/写入调用)。
对于COM posrts,我通常使用APC完成例程,其地址在readFileEx / writeFileEx API中传递。这使得_OVL的hEvent字段可以自由地用来保存缓冲区的实例指针,因此很容易将它强制转换回完成例程,这意味着每个缓冲区类实例都包含一个_OVL memebr,它包含一个指向hEvent字段的指针到缓冲类实例 - 听起来很奇怪,但工作正常。)