win32多線程-非同步程序呼叫(asynchronous Procedure Calls, APCs)

來源:互聯網
上載者:User

      使用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 finishedHANDLE  ghEvent;// Keep track of each individual I/O operationOVERLAPPED gOverlapped[MAX_REQUESTS];// Handle to the file of interest.HANDLE ghFile;// Need a place to put all this datachar 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.\n",        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\n", 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!!\n");    // 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.\n", 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.\n");    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.\n");exit(EXIT_FAILURE);    }}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.