* 1 CancelIo Cancels all pending I/O operations that are issued by the calling thread for a specified file handle.
* 2 CancelIoEx Marks all pending I/O operations for the specified file handle in the current process as canceled, regardless of which thread created the I/O operation.
* 3 CancelSynchronousIo Marks pending synchronous I/O operations that are issued by the specified thread as canceled.
* 4 GetOverlappedResult Retrieves the results of an overlapped operation.
* 5 ReadFile Reads data from a file, starting at the position that is indicated by a file pointer. This function can operate synchronously and asynchronously.
* 6 WriteFile Writes data to a file at a position that a file pointer specifies. This function can operate synchronously and asynchronously.
*
ReadFile, 读取文件。
主要参数:1. 异步I/O句柄。
5. 指针,函数用来储存Overlapped结构,设置事件对象,读取的起始地址(Offset)。
WriteFile, 写文件。
主要参数:1. 异步I/O句柄。
5. 指针,Overlapped结构,储存文件操作信息,设置事件对象,写入的起始地址(Offset)。
GetOverlappedResult, 获得异步I/O操作状态或等待一个I/O执行完成。
CancelSynchronousIo, 发送一个自定义的I/O操作到完成端口队列,它的参数对应到GetQueuedCompletionStatus接收函数
主要参数:1.异步I/O句柄
CancelIo, 取消当前进程中某一个或全部正在执行中的异步I/O操作。
主要参数:1. 异步I/O句柄
2. OVERLAPPED结构,指定的I/O操作。
CancelIoEx, 取消当前线程中所有进行中的异步I/O操作。
主要参数:1. 异步I/O句柄
#include <stdio.h>
#include <windows.h>
// WARNING !!! All list items must be aligned on a MEMORY_ALLOCATION_ALIGNMENT boundary;
// WARNING !!! otherwise, this function will behave unpredictably.
#define MAX_THREADS 5
#define ERR_MSG(m) \
if (!PrintMessage(GetLastError(), NULL)) \
fprintf(stderr, m);
#define FATAL_ERROR(m) \
{ \
ERR_MSG(m) \
goto Exception; \
}
volatile BOOL bLoop;
BYTE
buffer_demo[1024];
DWORD
dwOperate,
dwBytesXfreed;
HANDLE
hEventIo;
BOOL
PrintMessage(errorId, format)
long errorId;
char *format;
{
LPSTR
text = NULL;
DWORD
length;
// Gets the message string by an error code.
length = FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, errorId, 0,
(LPSTR)&text,
0, NULL);
if (length == 0)
{
fprintf(stderr, "FormatMessage was failed, error:0x%08x, format:0x%08x\n", GetLastError(), errorId);
return FALSE;
}
if (format != NULL)
fprintf(stderr, format, text);
else
fprintf(stderr, text);
// Free the buffer allocate by the FormatMessage function.
LocalFree(text);
return TRUE;
}
DWORD WINAPI
pfnProcThread(data)
LPVOID data;
{
HANDLE
hFile = (HANDLE)data;
DWORD
error,
transferred;
BOOL
bResult = FALSE;
OVERLAPPED
overlap;
while (TRUE)
{
WaitForSingleObject(hEventIo, INFINITE);
if (!bLoop)
break;
/* GetOverlappedResult
Parameters
hFile [in]
A handle to the file, named pipe, or communications device. This is the same handle that was specified when the
overlapped operation was started by a call to below functions
1 ReadFile
2 WriteFile
3 ConnectNamedPipe
4 TransactNamedPipe
5 DeviceIoControl
6 WaitCommEvent
lpOverlapped [in]
A pointer to an OVERLAPPED structure that was specified when the overlapped operation was started.
lpNumberOfBytesTransferred [out]
A pointer to a variable that receives the number of bytes that were actually transferred by a read or write operation.
For a TransactNamedPipe operation, this is the number of bytes that were read from the pipe. For a DeviceIoControl operation,
this is the number of bytes of output data returned by the device driver. For a ConnectNamedPipe or WaitCommEvent operation,
this value is undefined.
bWait [in]
If this parameter is TRUE, the function does not return until the operation has been completed. If this parameter is FALSE and
the operation is still pending, the function returns FALSE and the GetLastError function returns ERROR_IO_INCOMPLETE.
Return Value
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended error information, call GetLastError.
Remarks
The results reported by the GetOverlappedResult function are those of the specified handle's last overlapped operation to which
the specified OVERLAPPED structure was provided, and for which the operation's results were pending. A pending operation is indicated
when the function that started the operation returns FALSE, and the GetLastError function returns ERROR_IO_PENDING. When an I/O
operation is pending, the function that started the operation resets the hEvent member of the OVERLAPPED structure to the nonsignaled
state. Then when the pending operation has been completed, the system sets the event object to the signaled state. Specify a manual-reset
event object in the OVERLAPPED structure. If an auto-reset event object is used, the event handle must not be specified in any other wait
operation in the interval between starting the overlapped operation and the call to GetOverlappedResult. For example, the event object is
sometimes specified in one of the wait functions to wait for the operation's completion. When the wait function returns, the system sets
an auto-reset event's state to nonsignaled, and a subsequent call to GetOverlappedResult with the bWait parameter set to TRUE causes the
function to be blocked indefinitely. If the bWait parameter is TRUE, GetOverlappedResult determines whether the pending operation has
been completed by waiting for the event object to be in the signaled state. If the hEvent member of the OVERLAPPED structure is NULL,
the system uses the state of the hFile handle to signal when the operation has been completed. Use of file, named pipe, or
communications-device handles for this purpose is discouraged. It is safer to use an event object because of the confusion that can
occur when multiple simultaneous overlapped operations are performed on the same file, named pipe, or communications device. In this
situation, there is no way to know which operation caused the object's state to be signaled.
*/
if (GetOverlappedResult(hFile, &overlap, &transferred, FALSE))
{
if (dwOperate == 0)
fprintf(stdout, "READ COMPLETED T %04X, D %04d, K %04d\n", GetCurrentThreadId(), transferred, dwBytesXfreed);
else
fprintf(stdout, "WRITE COMPLETED T %04X, D %04d, K %04d\n", GetCurrentThreadId(), transferred, dwBytesXfreed);
}
else
{
switch (error = GetLastError())
{
case ERROR_HANDLE_EOF:
fprintf(stdout, "GetOverlappedResult found EOF\n");
break;
case ERROR_IO_INCOMPLETE:
fprintf(stdout, "GetOverlappedResult I/O Incomplete\n");
break;
default:
fprintf(stdout, "GetOverlappedResult I/O unknown error %d\n", error);
}
}
ResetEvent(hEventIo);
Sleep(100);
}
fprintf(stdout, "Thread %04X was exited.\n", GetCurrentThreadId());
return 0;
}
BOOL
WaitForUserKeyInput(key, exitkey, keydown)
LPDWORD key;
DWORD exitkey;
BOOL keydown;
{
DWORD
length;
INPUT_RECORD
record;
*key = -1;
if (!ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &record, 1, &length) ||
!length)
{
ERR_MSG("Failed to get user key input.");
Sleep(100);
// 读取键盘输入失败,返回TRUE进入下一个读取动作。
return TRUE;
}
if (record.EventType != KEY_EVENT ||
!(keydown ? record.Event.KeyEvent.bKeyDown: !record.Event.KeyEvent.bKeyDown))
return TRUE;
// 返回当前KEY值。
*key = record.Event.KeyEvent.wVirtualKeyCode;
// 如果是指定的退出按键或ESC则返回FALSE。
return !(*key == exitkey || *key == VK_ESCAPE);
}
int
main()
{
DWORD
i;
HANDLE
hFile = NULL,
hThread = NULL;
INPUT_RECORD
record;
OVERLAPPED
overlap;
CHAR
szFilePath[MAX_PATH];
GetModuleFileName(NULL, szFilePath, MAX_PATH);
i = strlen(szFilePath);
while (szFilePath[--i] != '\\');
strcpy(&szFilePath[i], "\\data.dat");
hFile = CreateFile(szFilePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED, NULL);
if (hFile == INVALID_HANDLE_VALUE)
FATAL_ERROR("Failed to create test file.\n");
hEventIo = CreateEvent(NULL, TRUE, FALSE, "MyEvent1");
if (hEventIo == NULL)
FATAL_ERROR("Failed to create event object.\n");
bLoop = TRUE;
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)pfnProcThread, (LPVOID)hFile, 0, NULL);
if (hThread == NULL)
FATAL_ERROR("Failed to create thread object.\n");
RtlFillMemory(buffer_demo, 1024, 52);
ZeroMemory(&overlap, sizeof(OVERLAPPED));
overlap.hEvent = hEventIo;
while (WaitForUserKeyInput(&i, VK_RETURN, TRUE))
{
switch (i)
{
case VK_UP:
dwOperate = 0;
/*
OVERLAPPED structure used for ReadFile function.
If hFile is opened with FILE_FLAG_OVERLAPPED, the lpOverlapped parameter must point to a valid and unique OVERLAPPED
structure, otherwise the function can incorrectly report that the read operation is complete. For an hFile that supports
byte offsets, if you use this parameter you must specify a byte offset at which to start reading from the file or device.
This offset is specified by setting the Offset and OffsetHigh members of the OVERLAPPED structure. For an hFile that does
not support byte offsets, Offset and OffsetHigh are ignored.
*/
overlap.Offset = 0;
overlap.OffsetHigh = 0;
ReadFile(hFile, buffer_demo, 1024, &dwBytesXfreed, &overlap);
i = GetLastError();
if (i != ERROR_IO_PENDING)
PrintMessage(i);
break;
case VK_DOWN:
dwOperate = 1;
/*
OVERLAPPED structure used for WriteFile function.
For an hFile that supports byte offsets, if you use this parameter you must specify a byte offset at which to start
writing to the file or device. This offset is specified by setting the Offset and OffsetHigh members of the OVERLAPPED
structure. For an hFile that does not support byte offsets, Offset and OffsetHigh are ignored. To write to the end of
file, specify both the Offset and OffsetHigh members of the OVERLAPPED structure as 0xFFFFFFFF. This is functionally
equivalent to previously calling the CreateFile function to open hFile using FILE_APPEND_DATA access.
*/
overlap.Offset = 0xFFFFFFFF;
overlap.OffsetHigh = 0xFFFFFFFF;
WriteFile(hFile, buffer_demo, 1024, &dwBytesXfreed, &overlap);
i = GetLastError();
if (i != ERROR_IO_PENDING)
PrintMessage(i);
break;
case VK_LEFT:
if (!CancelIo(hFile))
ERR_MSG("Failed to cancel the I/O operations.");
break;
case VK_RIGHT:
break;
}
}
bLoop = FALSE;
// PulseEvent(hEventIo);
// Ensure that the event object is the signed status.
SetEvent(hEventIo);
WaitForSingleObject(hThread, INFINITE);
Exception:
if (hThread)
{
CloseHandle(hThread);
hThread = NULL;
}
if (hEventIo)
CloseHandle(hEventIo);
if (hFile && hFile != INVALID_HANDLE_VALUE)
CloseHandle(hFile);
return 0;
}