win32多线程-异步(asynchronous) I/O

来源:互联网 发布:乐视网络大电影合作 编辑:程序博客网 时间:2024/06/10 20:08

        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 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 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\n", szPath);        return -1;    }    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.    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.\n",                    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.\n", 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.\n", 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.\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, "IoByEvnt must be run under Windows NT.\n");exit(EXIT_FAILURE);    }}

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

原创粉丝点击