zoukankan      html  css  js  c++  java
  • win32多线程-异步过程调用(asynchronous Procedure Calls, APCs)

          使用overlapped I/O并搭配event对象-----win32多线程-异步(asynchronous) I/O事例,会产生两个基础性问题。
    第一个问题是,使用WaitForMultipleObjects(),你只能等待最多达MAXIMUM_WAIT_OBJECTS个对象,在Windows NT中此值最大为64。
    第二个问题是,你必须不断根据“那一个handle被激发”而计算如何反应。你必须有一个分派表格(dispatch table)和WaitForMultipleObjects()的handles数组结合起来。
          这两个问题可以靠一个所谓的异步过程调用(asynchronous Procedure Calls, APCs)解决,只要使用“Ex”版的ReadFile()和WriteFile(),你就可以调用这个机制。这两个函数允许你指定一个额外的参数,是一个callback函数,这个callback函数被称为I/O completion routine,因为系统是在某一个特别的overlapped I/O操作完成之后调用它。

    异步过程调用事例:

    /*
     * IoByAPC.c
     *
     * Sample code for Multithreading Applications in Win32
     * This is from Chapter 6, Listing 6-3
     *
     * Demonstrates how to use APC's (asynchronous
     * procedure calls) instead of signaled objects
     * to service multiple outstanding overlapped
     * operations 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
    //
    void CheckOsVersion();
    int QueueRequest(int nIndex, DWORD dwLocation, DWORD dwAmount);
    
    
    //
    // Global variables
    //
    
    // Need a single event object so we know when all I/O is finished
    HANDLE  ghEvent;
    // 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 nCompletionCount;
    
    /*
     * I/O Completion routine gets called
     * when app is alertable (in WaitForSingleObjectEx)
     * and an overlapped I/O operation has completed.
     */
    VOID WINAPI FileIOCompletionRoutine(
        DWORD dwErrorCode,  // completion code 
        DWORD dwNumberOfBytesTransfered,    // number of bytes transferred 
        LPOVERLAPPED lpOverlapped   // pointer to structure with I/O information  
       )
    {
        // The event handle is really the user defined data
        int nIndex = (int)(lpOverlapped->hEvent);
        printf("Read #%d returned %d. %d bytes were read.
    ",
            nIndex,
            dwErrorCode,
            dwNumberOfBytesTransfered);
    
        if (++nCompletionCount == MAX_REQUESTS)
            SetEvent(ghEvent);  // Cause the wait to terminate
    }
    
    
    int main()
    {
        int i;
        char szPath[MAX_PATH];
    
        CheckOsVersion();
    
        // Need to know when to stop
        MTVERIFY(
            ghEvent = CreateEvent(
                         NULL,    // No security
                         TRUE,    // Manual reset - extremely important!
                         FALSE,   // Initially set Event to non-signaled state
                         NULL     // No name
                        )
        );
    
        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;
        }
    
        // Queue up a few requests
        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.
        for (;;)
        {
            DWORD rc;
            rc = WaitForSingleObjectEx(ghEvent, INFINITE, TRUE );
            if (rc == WAIT_OBJECT_0)
                break;
            MTVERIFY(rc == WAIT_IO_COMPLETION);
        }
    
        CloseHandle(ghFile);
    
    	getchar();
        return EXIT_SUCCESS;
    }
    
    
    /*
     * Call ReadFileEx to start an overlapped request.
     * Make sure we handle errors that are recoverable.
     */
    int QueueRequest(int nIndex, DWORD dwLocation, DWORD dwAmount)
    {
        int i;
        BOOL rc;
        DWORD err;
    
        gOverlapped[nIndex].hEvent = (HANDLE)nIndex;
        gOverlapped[nIndex].Offset = dwLocation;
    
        for (i=0; i<MAX_TRY_COUNT; i++)
        {
            rc = ReadFileEx(
                ghFile,
                gBuffers[nIndex],
                dwAmount,
                &gOverlapped[nIndex],
                FileIOCompletionRoutine
            );
    
            // Handle success
            if (rc)
            {
                // asynchronous i/o is still in progress 
                printf("Read #%d queued for overlapped I/O.
    ", nIndex);
                return TRUE;
            }
    
            err = GetLastError();
    
            // 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("ReadFileEx 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, "IoByAPC must be run under Windows NT.
    ");
    		exit(EXIT_FAILURE);
        }
    
    }
    
  • 相关阅读:
    234. Palindrome Linked List
    Remove duplicates
    Unsorted, maximum ==> sorted
    Find one unique integer
    TwoSum
    13. Roman to Integer
    38. Count and Say
    543. Diameter of Binary Tree
    LuoguP1131 [ZJOI2007]时态同步 (树形DP,贪心)
    Luogu3177 [HAOI2015]树上染色 (树形DP)
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3225869.html
Copyright © 2011-2022 走看看