1

我想检查 WriteFile 函数是否已完成对 UART 的写入,以便我可以在同一个 ComDev 上调用 ReadFile 而不会导致异常。

似乎WriteFile 函数可以在写入完成之前返回。

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) 作为解决方法,但我该如何等待适当的时间?

4

5 回答 5

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 超时也不可能。

于 2012-08-17T21:14:45.677 回答
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、完成端口等。您的程序流逻辑也应该更改。

于 2012-08-17T21:20:10.897 回答
0

Sleep(1000);没有用,它只会在writefile完成操作后执行。你必须等到WriteFile结束。

if(WriteFile(*pComDev,pBuffer,BytesToWrite,&BytesWritten,&osWrite) == FALSE)
{}

您必须知道,条件中的任何内容只有在结果为真时才会执行。在这里,在 WriteFile 例程完成(无论是完成还是错误)后,结果被发送到程序。

于 2012-08-17T21:08:17.653 回答
0

既然你没有说你需要异步 I/O,你应该尝试同步。这更容易。我认为,如果您只是为 OVERLAPPED arg 传递一个空指针,您将获得同步、阻塞、I/O。请参阅我在本文档的“Windows C”部分编写的示例代码:

http://www.pololu.com/docs/0J40/

于 2012-08-17T21:30:04.797 回答
0

好的,我错过了读/写代码中重叠的 I/O OVL 参数,所以我昨天才回复作为评论,否则我会被否决:(

The classic way of handling overlapped I/O is to have an _OVL struct as a data member of the buffer class that is issued in the overlapped read/write call. This makes it easy to have read and write calls loaded in at the same time, (or indeed, multiple read/write calls with separate buffer instances).

For COM posrts, I usually use an APC completion routine whose address is passed in the readFileEx/writeFileEx APIs. This leaves the hEvent field of the _OVL free to use to hold the instance pointer of the buffer so it's easy to cast it back inside the completion routine, (this means that each buffer class instance contains an _OVL memebr that contains an hEvent field that points to the buffer class instance - sounds a but weird, but works fine).

于 2012-08-18T08:30:48.367 回答