win32多线程-异步过程调用(asynchronous Procedure Calls, APCs)
使用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 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, // 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);
- }
- }
win32多线程-异步过程调用(asynchronous Procedure Calls, APCs)的更多相关文章
- win32多线程-异步(asynchronous) I/O
I/O设备是个慢速设备,无论打印机.调制解调器,甚至硬盘,与CPU相比都奇慢无比,坐下来干等I/O的完成是一件不甚明智事情. 异步(asynchronous) I/O在win32多线程程序设计中被称为 ...
- 深入浅出Win32多线程程序设计之基本概念
一.深入浅出Win32多线程程序设计之基本概念[转] 引言 从单进程单线程到多进程多线程是操作系统发展的一种必然趋势,当年的DOS系统属于单任务操作系统,最优秀的程序员也只能通过驻留内存的方式实现所谓 ...
- APC -- Asynchronous Procedure Call 异步过程调用
异步过程调用(APC -- Asynchronous Procedure Call )是一种与常用的和简单的同步对象不同的一种同步机制. 我们在我们线程里使用基本的同步对象如MUTEX去通知其它线程, ...
- 多线程学习:win32多线程编程基本概念(转)
一.定义: 1.进程和线程的区别 进程:是程序的执行过程,具有动态性,即运行的程序就叫进程,不运行就叫程序 ,每个进程包含一到多个线程.线程:系统中的最小执行单元,同一进程中有多个线程,线程可以共享资 ...
- AsyncCalls – Asynchronous function calls
AsyncCalls – Asynchronous function callsWith AsyncCalls you can execute multiple functions at the sa ...
- Win32多线程编程(1) — 基础概念篇
内核对象的基本概念 Windows系统是非开源的,它提供给我们的接口是用户模式的,即User-Mode API.当我们调用某个API时,需要从用户模式切换到内核模式的I/O System Serv ...
- 由《win32多线程程序设计》临界区的问题所想
之前看侯捷翻译的<win32多线程程序设计>中关于线程同步中的临界区问题,其中举得例子是对链表的操作.死锁的问题是对一个Swaplist函数的问题,现列举代码如下: void SwapLi ...
- Win32多线程编程(3) — 线程同步与通信
一.线程间数据通信 系统从进程的地址空间中分配内存给线程栈使用.新线程与创建它的线程在相同的进程上下文中运行.因此,新线程可以访问进程内核对象的所有句柄.进程中的所有内存以及同一个进程中其他所有线 ...
- Win32 多线程的创建方法和基本使用
Win32多线程的创建方法主要有: (1)CreateThread() (2)_beginthread()&&_beginthreadex() (3)AfxBeginThread() ...
随机推荐
- Android 内存管理 &Memory Leak & OOM 分析
1.Android 流程管理&内存 Android主要应用在嵌入式设备其中.而嵌入式设备因为一些众所周知的条件限制,通常都不会有非常高的配置,特别是内存是比較有限的. 假设我们编写的代 码其中 ...
- HttpGet 请求
import java.net.HttpURLConnection; import java.text.SimpleDateFormat; import java.util.Calendar; imp ...
- Java设计模式(四) 装饰 代理模式
(七)装饰 Decorator 装饰是一个对象,以动态地增加一些新功能. 象与被装饰的对象须要实现同一个接口.装饰对象持有被装饰对象的实例. interface DecoratorSourceable ...
- .NET 对象序列化和系列化德
DataSet ds = new DataSet(); //给ds赋值(省略) byte[] b = this.Serialize(ds); DataSet d1 = this.DeSerialize ...
- js手机对应的多级导航分享
js移动导航对应,您可以使用自适应时屏幕,当小画面在一定程度上的网站.使导航出现,The navigation effects such as the following figures:多级导航! ...
- Postman 是一个非常棒的Chrome扩展,提供功能强大的API & HTTP 请求调试
Postman 是一个非常棒的Chrome扩展,提供功能强大的API & HTTP 请求调试 需要FQ才能安装,使用时应该不用FQ了,除非使用postman的历史记录功能: 非常棒的C ...
- maven和libgdx
这一篇是关于maven和libgdx的.本来我准备用gradle(现已有gradle模板了),不过暂时有点小问题,而同时libgdx官方提供了maven支持,为了快速上手还是选用maven了. 博客已 ...
- SSAS系列——【02】多维数据(维度对象)
原文:SSAS系列——[02]多维数据(维度对象) 1.维度是什么? 数学中叫参数,物理学中是独立的时空坐标的数目.0维是一点,1维是线,2维是一个长和宽(或曲线)面积,3维是2维加上高度形成体积面. ...
- Hibernate 之强大的HQL查询
Hibernate 配备了一种非常强大的查询语言,这种语言看上去很像 SQL.但是不要被语法结构上的相似所迷惑,HQL 是非常有意识的被设计为完全面向对象的查询,它可以理解如继承.多态和关联之类 ...
- :link,:visited,:focus,:hover,:active详解
原文::link,:visited,:focus,:hover,:active详解 CSS 又名 层叠样式表,所谓层叠,就是后面的样式会覆盖前面的样式,所以在样式表中,各样式排列的顺序很有讲究. ...