使用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操作完成之后调用它。

异步过程调用事例:

  1. /*
  2. * IoByAPC.c
  3. *
  4. * Sample code for Multithreading Applications in Win32
  5. * This is from Chapter 6, Listing 6-3
  6. *
  7. * Demonstrates how to use APC's (asynchronous
  8. * procedure calls) instead of signaled objects
  9. * to service multiple outstanding overlapped
  10. * operations on a file.
  11. */
  12.  
  13. #define WIN32_LEAN_AND_MEAN
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <windows.h>
  17. #include "MtVerify.h"
  18.  
  19. //
  20. // Constants
  21. //
  22. #define MAX_REQUESTS 5
  23. #define READ_SIZE 512
  24. #define MAX_TRY_COUNT 5
  25.  
  26. //
  27. // Function prototypes
  28. //
  29. void CheckOsVersion();
  30. int QueueRequest(int nIndex, DWORD dwLocation, DWORD dwAmount);
  31.  
  32. //
  33. // Global variables
  34. //
  35.  
  36. // Need a single event object so we know when all I/O is finished
  37. HANDLE ghEvent;
  38. // Keep track of each individual I/O operation
  39. OVERLAPPED gOverlapped[MAX_REQUESTS];
  40. // Handle to the file of interest.
  41. HANDLE ghFile;
  42. // Need a place to put all this data
  43. char gBuffers[MAX_REQUESTS][READ_SIZE];
  44. int nCompletionCount;
  45.  
  46. /*
  47. * I/O Completion routine gets called
  48. * when app is alertable (in WaitForSingleObjectEx)
  49. * and an overlapped I/O operation has completed.
  50. */
  51. VOID WINAPI FileIOCompletionRoutine(
  52. DWORD dwErrorCode, // completion code
  53. DWORD dwNumberOfBytesTransfered, // number of bytes transferred
  54. LPOVERLAPPED lpOverlapped // pointer to structure with I/O information
  55. )
  56. {
  57. // The event handle is really the user defined data
  58. int nIndex = (int)(lpOverlapped->hEvent);
  59. printf("Read #%d returned %d. %d bytes were read.\n",
  60. nIndex,
  61. dwErrorCode,
  62. dwNumberOfBytesTransfered);
  63.  
  64. if (++nCompletionCount == MAX_REQUESTS)
  65. SetEvent(ghEvent); // Cause the wait to terminate
  66. }
  67.  
  68. int main()
  69. {
  70. int i;
  71. char szPath[MAX_PATH];
  72.  
  73. CheckOsVersion();
  74.  
  75. // Need to know when to stop
  76. MTVERIFY(
  77. ghEvent = CreateEvent(
  78. NULL, // No security
  79. TRUE, // Manual reset - extremely important!
  80. FALSE, // Initially set Event to non-signaled state
  81. NULL // No name
  82. )
  83. );
  84.  
  85. GetWindowsDirectory(szPath, sizeof(szPath));
  86. strcat(szPath, "\\WINHLP32.EXE");
  87. // Open the file for overlapped reads
  88. ghFile = CreateFile( szPath,
  89. GENERIC_READ,
  90. FILE_SHARE_READ|FILE_SHARE_WRITE,
  91. NULL,
  92. OPEN_EXISTING,
  93. FILE_FLAG_OVERLAPPED,
  94. NULL
  95. );
  96. if (ghFile == INVALID_HANDLE_VALUE)
  97. {
  98. printf("Could not open %s\n", szPath);
  99. return -1;
  100. }
  101.  
  102. // Queue up a few requests
  103. for (i=0; i<MAX_REQUESTS; i++)
  104. {
  105. // Read some bytes every few K
  106. QueueRequest(i, i*16384, READ_SIZE);
  107. }
  108.  
  109. printf("QUEUED!!\n");
  110.  
  111. // Wait for all the operations to complete.
  112. for (;;)
  113. {
  114. DWORD rc;
  115. rc = WaitForSingleObjectEx(ghEvent, INFINITE, TRUE );
  116. if (rc == WAIT_OBJECT_0)
  117. break;
  118. MTVERIFY(rc == WAIT_IO_COMPLETION);
  119. }
  120.  
  121. CloseHandle(ghFile);
  122.  
  123. getchar();
  124. return EXIT_SUCCESS;
  125. }
  126.  
  127. /*
  128. * Call ReadFileEx to start an overlapped request.
  129. * Make sure we handle errors that are recoverable.
  130. */
  131. int QueueRequest(int nIndex, DWORD dwLocation, DWORD dwAmount)
  132. {
  133. int i;
  134. BOOL rc;
  135. DWORD err;
  136.  
  137. gOverlapped[nIndex].hEvent = (HANDLE)nIndex;
  138. gOverlapped[nIndex].Offset = dwLocation;
  139.  
  140. for (i=0; i<MAX_TRY_COUNT; i++)
  141. {
  142. rc = ReadFileEx(
  143. ghFile,
  144. gBuffers[nIndex],
  145. dwAmount,
  146. &gOverlapped[nIndex],
  147. FileIOCompletionRoutine
  148. );
  149.  
  150. // Handle success
  151. if (rc)
  152. {
  153. // asynchronous i/o is still in progress
  154. printf("Read #%d queued for overlapped I/O.\n", nIndex);
  155. return TRUE;
  156. }
  157.  
  158. err = GetLastError();
  159.  
  160. // Handle recoverable error
  161. if ( err == ERROR_INVALID_USER_BUFFER ||
  162. err == ERROR_NOT_ENOUGH_QUOTA ||
  163. err == ERROR_NOT_ENOUGH_MEMORY )
  164. {
  165. Sleep(50); // Wait around and try later
  166. continue;
  167. }
  168.  
  169. // Give up on fatal error.
  170. break;
  171. }
  172.  
  173. printf("ReadFileEx failed.\n");
  174. return -1;
  175. }
  176.  
  177. //
  178. // Make sure we are running under an operating
  179. // system that supports overlapped I/O to files.
  180. //
  181. void CheckOsVersion()
  182. {
  183. OSVERSIONINFO ver;
  184. BOOL bResult;
  185.  
  186. ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  187.  
  188. bResult = GetVersionEx((LPOSVERSIONINFO) &ver);
  189.  
  190. if ( (!bResult) ||
  191. (ver.dwPlatformId != VER_PLATFORM_WIN32_NT) )
  192. {
  193. fprintf(stderr, "IoByAPC must be run under Windows NT.\n");
  194. exit(EXIT_FAILURE);
  195. }
  196.  
  197. }

win32多线程-异步过程调用(asynchronous Procedure Calls, APCs)的更多相关文章

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

    I/O设备是个慢速设备,无论打印机.调制解调器,甚至硬盘,与CPU相比都奇慢无比,坐下来干等I/O的完成是一件不甚明智事情. 异步(asynchronous) I/O在win32多线程程序设计中被称为 ...

  2. 深入浅出Win32多线程程序设计之基本概念

    一.深入浅出Win32多线程程序设计之基本概念[转] 引言 从单进程单线程到多进程多线程是操作系统发展的一种必然趋势,当年的DOS系统属于单任务操作系统,最优秀的程序员也只能通过驻留内存的方式实现所谓 ...

  3. APC -- Asynchronous Procedure Call 异步过程调用

    异步过程调用(APC -- Asynchronous Procedure Call )是一种与常用的和简单的同步对象不同的一种同步机制. 我们在我们线程里使用基本的同步对象如MUTEX去通知其它线程, ...

  4. 多线程学习:win32多线程编程基本概念(转)

    一.定义: 1.进程和线程的区别 进程:是程序的执行过程,具有动态性,即运行的程序就叫进程,不运行就叫程序 ,每个进程包含一到多个线程.线程:系统中的最小执行单元,同一进程中有多个线程,线程可以共享资 ...

  5. AsyncCalls – Asynchronous function calls

    AsyncCalls – Asynchronous function callsWith AsyncCalls you can execute multiple functions at the sa ...

  6. Win32多线程编程(1) — 基础概念篇

      内核对象的基本概念 Windows系统是非开源的,它提供给我们的接口是用户模式的,即User-Mode API.当我们调用某个API时,需要从用户模式切换到内核模式的I/O System Serv ...

  7. 由《win32多线程程序设计》临界区的问题所想

    之前看侯捷翻译的<win32多线程程序设计>中关于线程同步中的临界区问题,其中举得例子是对链表的操作.死锁的问题是对一个Swaplist函数的问题,现列举代码如下: void SwapLi ...

  8. Win32多线程编程(3) — 线程同步与通信

      一.线程间数据通信 系统从进程的地址空间中分配内存给线程栈使用.新线程与创建它的线程在相同的进程上下文中运行.因此,新线程可以访问进程内核对象的所有句柄.进程中的所有内存以及同一个进程中其他所有线 ...

  9. Win32 多线程的创建方法和基本使用

    Win32多线程的创建方法主要有: (1)CreateThread() (2)_beginthread()&&_beginthreadex() (3)AfxBeginThread() ...

随机推荐

  1. Android 内存管理 &amp;Memory Leak &amp; OOM 分析

    1.Android 流程管理&内存 Android主要应用在嵌入式设备其中.而嵌入式设备因为一些众所周知的条件限制,通常都不会有非常高的配置,特别是内存是比較有限的. 假设我们编写的代 码其中 ...

  2. HttpGet 请求

    import java.net.HttpURLConnection; import java.text.SimpleDateFormat; import java.util.Calendar; imp ...

  3. Java设计模式(四) 装饰 代理模式

    (七)装饰 Decorator 装饰是一个对象,以动态地增加一些新功能. 象与被装饰的对象须要实现同一个接口.装饰对象持有被装饰对象的实例. interface DecoratorSourceable ...

  4. .NET 对象序列化和系列化德

    DataSet ds = new DataSet(); //给ds赋值(省略) byte[] b = this.Serialize(ds); DataSet d1 = this.DeSerialize ...

  5. js手机对应的多级导航分享

    js移动导航对应,您可以使用自适应时屏幕,当小画面在一定程度上的网站.使导航出现,The navigation effects such as the following figures:多级导航! ...

  6. Postman 是一个非常棒的Chrome扩展,提供功能强大的API & HTTP 请求调试

    Postman 是一个非常棒的Chrome扩展,提供功能强大的API & HTTP 请求调试   需要FQ才能安装,使用时应该不用FQ了,除非使用postman的历史记录功能:   非常棒的C ...

  7. maven和libgdx

    这一篇是关于maven和libgdx的.本来我准备用gradle(现已有gradle模板了),不过暂时有点小问题,而同时libgdx官方提供了maven支持,为了快速上手还是选用maven了. 博客已 ...

  8. SSAS系列——【02】多维数据(维度对象)

    原文:SSAS系列——[02]多维数据(维度对象) 1.维度是什么? 数学中叫参数,物理学中是独立的时空坐标的数目.0维是一点,1维是线,2维是一个长和宽(或曲线)面积,3维是2维加上高度形成体积面. ...

  9. Hibernate 之强大的HQL查询

    Hibernate  配备了一种非常强大的查询语言,这种语言看上去很像  SQL.但是不要被语法结构上的相似所迷惑,HQL  是非常有意识的被设计为完全面向对象的查询,它可以理解如继承.多态和关联之类 ...

  10. :link,:visited,:focus,:hover,:active详解

    原文::link,:visited,:focus,:hover,:active详解 CSS 又名 层叠样式表,所谓层叠,就是后面的样式会覆盖前面的样式,所以在样式表中,各样式排列的顺序很有讲究.   ...