zoukankan      html  css  js  c++  java
  • 关于GetOverlappedResult函数的一些知识

    之前在写重叠IO的代码的时候,记得那时是从网络上拷贝的代码例子。在关于重叠操作的等待结果时,一般都是如下的过程:

    先  调用waitformultipleobject或waitforsingleobject函数来等待某一个IO请求绑定的事件对象的激活。等到激活事件对象后,再调用GetOverlappedResult函数取得重叠IO的结果,这里GetOverlappedResult的返回值一般都是TRUE(即重叠操作成功)。

    代码如下:

    rc = ReadFile(hFile,buf,300,&numread,&overlap);
    //因为是overlapped操作,ReadFile会将读文件请求放入读队列之后立即返回(false),
    //而不会等到文件读完才返回(true)
    if (rc)
    {
    //文件真是被读完了,rc为true
    // 或当数据被放入cache中,或操作系统认为它可以很快速地取得数据,rc为true
    }
    else
    {
    if (GetLastError() == ERROR_IO_PENDING)
    {//当错误是ERROR_IO_PENDING,那意味着读文件的操作还在进行中
    //等候,直到文件读完
    WaitForSingleObject(hFile, INFINITE);
    rc = GetOverlappedResult(hFile,&overlap,&numread,FALSE);
    //上面二条语句完成的功能与下面一条语句的功能等价:
    // GetOverlappedResult(hFile,&overlap,&numread,TRUE);
    }
    else
    {
    //出错了
    }
    }
    CloseHandle(hFile);

    如果这样做也可以,不用关心一些关于getoverlappedresult函数的细节。

    现在深入研究下getoverlappedresult函数的细节:

    BOOL
    WINAPI
    GetOverlappedResult(
        HANDLE hFile,
        LPOVERLAPPED lpOverlapped,
        LPDWORD lpNumberOfBytesTransferred,
        BOOL bWait
        )

    下面是OVERLAPPED的结构定义:
    typedef struct _OVERLAPPED { 
        DWORD  Internal; 
        DWORD  InternalHigh; 
        DWORD  Offset; 
        DWORD  OffsetHigh; 
        HANDLE hEvent; 
    } OVERLAPPED; 

    其函数实现的伪代码为:

    {
        DWORD WaitReturn;
        // Did caller specify an event to the original operation or was the
        // default (file handle) used?
        //
        if (lpOverlapped->Internal == (DWORD)STATUS_PENDING ) {
            if ( bWait )

            {
                //
                //现在还是PENDING,且还需要等待,则无限期等待。
                //很多人会自己调用WaitForSingleObject后再调用GetOverlappedResult,其实看起来
                //没多少必要。
                //
                WaitReturn = WaitForSingleObject(
                                ( lpOverlapped->hEvent != NULL ) ?
                                    lpOverlapped->hEvent : hFile,
                                INFINITE
                                );
             }
            else

            {
                WaitReturn = WAIT_TIMEOUT;
            }

            if ( WaitReturn == WAIT_TIMEOUT )

            {
                //  !bWait and event in not signalled state
                SetLastError( ERROR_IO_INCOMPLETE );
                return FALSE;
            }

            if ( WaitReturn != 0 )

           {

                 return FALSE;    // WaitForSingleObject calls BaseSetLastError
            }
      }

        *lpNumberOfBytesTransferred = (DWORD)lpOverlapped->InternalHigh;

        if ( NT_SUCCESS((NTSTATUS)lpOverlapped->Internal) )

        {
            return TRUE;
        }
        else

       {

            BaseSetLastNTError( (NTSTATUS)lpOverlapped->Internal );
            return FALSE;
        }
    }

    由上面代码可以看出,Internal成员就是用来存储已经处理的IO请求的状态码。InternalHigh成员是在IO请求完成后,实际传输的字节数,如果没有完成,则这个成员值应该被忽略。

    WaitForSingleObject(hFile, INFINITE);
    rc = GetOverlappedResult(hFile,&overlap,&numread,FALSE);

    一般情况下waitsingle的第二个参数为INFINITE的话,除非出现什么其他IO错误,要不然等wait到事件对象后,IO操作都是已经成功完成了的。那么再调用Getoverlappedresult函数就会直接返回TRUE了。

    如果把waitsingle的第二个参数为某个超时时间值时,那么Getoverlappedresult函数的最后一个blwait参数最好设置为TRUE,这样的话才能保证Getoverlappedresult返回TRUE,要不然就会返回FALSE,而此时的GetLastError返回值就是ERROR_IO_INCOMPLETE 了,代表IO操作还未完成。

    或者是直接用Getoverlappedresult(hFile, &overlap, &numread, TRUE);这一句来完成上面两句的任务,效果一样。不过好像大家都是用的上面两句。

  • 相关阅读:
    四种方案解决ScrollView嵌套ListView问题
    [Android Bug] ListView中Header, Footer无法隐藏(gone)的问题
    Mysql介绍,与将脚本导入新数据库
    000 SpringBoot属性配置
    navicat的安装
    gradle
    004 Numpy
    003 Scipy库简介
    Mysql安装(绿色版安装)
    010 secondary namenode(同步元数据和日志)
  • 原文地址:https://www.cnblogs.com/Little-Star/p/7413331.html
Copyright © 2011-2022 走看看