异步过程调用(Asynchronous Procedure Call)

来源:互联网 发布:linux 读音 编辑:程序博客网 时间:2024/06/08 09:11

/*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);
}


}

0 0
原创粉丝点击