zoukankan      html  css  js  c++  java
  • win32多线程-异步(asynchronous) I/O

            I/O设备是个慢速设备,无论打印机、调制解调器,甚至硬盘,与CPU相比都奇慢无比,坐下来干等I/O的完成是一件不甚明智事情。

            异步(asynchronous) I/O在win32多线程程序设计中被称为overlapped I/O,是win32的一项技术,你可以要求操作系统为你传送数据,并且在传送完毕时通知你。这项技术使你的程序在I/O进行过程中仍然能够继续处理事务。事实上,操作系统内部正是以多线程完成overlapped I/O,你可以获得线程的所有利益,而不需要付出什么痛苦代价。

    异步(asynchronous) I/O事例:

    /*
     * IoByEvnt.c
     *
     * Sample code for Multithreading Applications in Win32
     * This is from Chapter 6, Listing 6-2
     *
     * Demonstrates how to use event objects instead of
     * file handles to signal multiple outstanding
     * overlapped operation on a file.
     */
    
    #define WIN32_LEAN_AND_MEAN
    #include <stdio.h>
    #include <stdlib.h>
    #include <windows.h>
    #include "MtVerify.h"
    
    //
    // Constants
    //
    #define MAX_REQUESTS    5
    #define READ_SIZE       512
    #define MAX_TRY_COUNT   5
    
    //
    // Function prototypes
    //
    int QueueRequest(int nIndex, DWORD dwLocation, DWORD dwAmount);
    void CheckOsVersion();
    
    
    //
    // Global variables
    //
    
    // Need to keep the events in their own array
    // so we can wait on them.
    HANDLE  ghEvents[MAX_REQUESTS];
    // Keep track of each individual I/O operation
    OVERLAPPED gOverlapped[MAX_REQUESTS];
    // Handle to the file of interest.
    HANDLE ghFile;
    // Need a place to put all this data
    char gBuffers[MAX_REQUESTS][READ_SIZE];
    
    
    int main()
    {
        int i;
        BOOL rc;
        char szPath[MAX_PATH];
    
        CheckOsVersion();
    
        GetWindowsDirectory(szPath, sizeof(szPath));
        strcat(szPath, "\WINHLP32.EXE");
        // Open the file for overlapped reads
        ghFile = CreateFile( szPath,
                        GENERIC_READ,
                        FILE_SHARE_READ|FILE_SHARE_WRITE,
                        NULL,
                        OPEN_EXISTING,
                        FILE_FLAG_OVERLAPPED,
                        NULL
                    );
        if (ghFile == INVALID_HANDLE_VALUE)
        {
            printf("Could not open %s
    ", szPath);
            return -1;
        }
    
        for (i=0; i<MAX_REQUESTS; i++)
        {
            // Read some bytes every few K
            QueueRequest(i, i*16384, READ_SIZE);
        }
    
        printf("QUEUED!!
    ");
    
        // Wait for all the operations to complete.
        MTVERIFY( WaitForMultipleObjects(
                   MAX_REQUESTS, ghEvents, TRUE, INFINITE
            ) != WAIT_FAILED );
    
        // Describe what just happened.
        for (i=0; i<MAX_REQUESTS; i++)
        {
            DWORD dwNumread;
    
            rc = GetOverlappedResult(
                                    ghFile,
                                    &gOverlapped[i],
                                    &dwNumread,
                                    FALSE
                                );
    		/************************************************************************/
    		/*调用GetOverlappedResult(),你获得的结果和“调用ReadFile()或WriteFile()而没有
    		指定overlapped I/O”所返回的东西一样,这个函数的价值在于,在文件操作真正完成之前,
    		你不可能确实知道它是否成功。
    		如果overlapped操作成功,此函数传回TRUE,失败则传回FALS。
    		如果GetOverlappedResult(,,, BOOL bWait)中的bWait为FALSE而overlapped还是没有完成,
    		GetLastError()返回ERROR_IO_INCOMPLETE.									*/
    		/************************************************************************/
            printf("Read #%d returned %d. %d bytes were read.
    ",
                        i, rc, dwNumread);
            CloseHandle(gOverlapped[i].hEvent);
        }
    
        CloseHandle(ghFile);
    
    	getchar();
        return EXIT_SUCCESS;
    }
    
    
    /*
     * Call ReadFile to start an overlapped request.
     * Make sure we handle errors that are recoverable.
     * Properly set up the event object for this operation.
     */
    int QueueRequest(int nIndex, DWORD dwLocation, DWORD dwAmount)
    {
        int i;
        BOOL rc;
        DWORD dwNumread;
        DWORD err;
    
        MTVERIFY(
            ghEvents[nIndex] = CreateEvent(
                         NULL,    // No security
                         TRUE,    // Manual reset - extremely important!
                         FALSE,   // Initially set Event to non-signaled state
                         NULL     // No name
                        )
        );
        gOverlapped[nIndex].hEvent = ghEvents[nIndex];
        gOverlapped[nIndex].Offset = dwLocation;
    
        for (i=0; i<MAX_TRY_COUNT; i++)
        {
            rc = ReadFile(
                ghFile,
                gBuffers[nIndex],
                dwAmount,
                &dwNumread,
                &gOverlapped[nIndex]
            );
    
            // Handle success
            if (rc)
            {
                printf("Read #%d completed immediately.
    ", nIndex);
                return TRUE;
            }
    
            err = GetLastError();
    
            // Handle the error that isn't an error. rc is zero here.
            if (err == ERROR_IO_PENDING)
            {
                // asynchronous i/o is still in progress 
                printf("Read #%d queued for overlapped I/O.
    ", nIndex);
                return TRUE;
            }
    
            // Handle recoverable error
            if ( err == ERROR_INVALID_USER_BUFFER ||
                 err == ERROR_NOT_ENOUGH_QUOTA ||
                 err == ERROR_NOT_ENOUGH_MEMORY )
            {
                Sleep(50);  // Wait around and try later
                continue;
            }
    
            // Give up on fatal error.
            break;
        }
    
        printf("ReadFile failed.
    ");
        return -1;
    }
    
    
    //
    // Make sure we are running under an operating
    // system that supports overlapped I/O to files.
    //
    void CheckOsVersion()
    {
        OSVERSIONINFO   ver;
        BOOL            bResult;
    
        ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    
        bResult = GetVersionEx((LPOSVERSIONINFO) &ver);
    
        if ( (!bResult) ||
             (ver.dwPlatformId != VER_PLATFORM_WIN32_NT) )
        {
            fprintf(stderr, "IoByEvnt must be run under Windows NT.
    ");
    		exit(EXIT_FAILURE);
        }
    
    }
    


    MtVerify.h头文件见-----win32多线程-新版本MtVerify.h

  • 相关阅读:
    A、B、C、D四个字母,能组成多少个互不相同且无重复三位组合
    一对老耗子,每个月都生一对小耗子。小耗子长3个月,第四个开始变成老耗子开始生! 假如都不死,那么请问24个月后有多少只耗子?
    猜数字大小游戏,用户输入一个数字,如果大了就显示大了,如果小了就显示小了, 如果对了就提示正确(补充难度,只有5次机会,限制数字的范围在百位以内)
    输出100-300中的任意两个数相同的三位数(不能三个数都相同)
    打印出A到Z的所有字符,使用char和int转换
    EmployeeMapper.xml例子,学习佟刚老师的myBatis课程,记录下的EmployeeMapper.xml,注释详细
    log4j.xml 精选的log4j.xml文档,比较详细,网上的版本很多,这个版本相对而言比较完整
    Win-Lin双系统重装Windows找回Linux启动
    素材下载网站
    Android系统备忘1
  • 原文地址:https://www.cnblogs.com/riskyer/p/3221578.html
Copyright © 2011-2022 走看看