您的位置:首页 > 其它

异步过程调用(Asynchronous Procedure Call)

2015-07-25 18:43 417 查看






/*Demonstrates how to use APC's(asynchronous procedure

calls)instread 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,

DWORD dwNumberOfBytesTransfered,

LPOVERLAPPED lpvOverlapped)

{

//The event handle is really the user defined data

int nIndex = (int)(lpvOverlapped->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, TRUE,

FALSE, NULL));

GetWindowsDirectory(LPWSTR(szPath), sizeof(szPath));

strcat(szPath, "\\WINHLP32.EXE");

//open the file for overlapped reads

ghFile = CreateFile(LPCWSTR(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);

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");

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, "OpByAPC must be run under Windows NT.\n");

exit(EXIT_FAILURE);

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: