I/O设备是个慢速设备,无论打印机、调制解调器,甚至硬盘,与CPU相比都奇慢无比,坐下来干等I/O的完成是一件不甚明智事情。

异步(asynchronous) I/O在win32多线程程序设计中被称为overlapped I/O,是win32的一项技术,你可以要求操作系统为你传送数据,并且在传送完毕时通知你。这项技术使你的程序在I/O进行过程中仍然能够继续处理事务。事实上,操作系统内部正是以多线程完成overlapped I/O,你可以获得线程的所有利益,而不需要付出什么痛苦代价。

异步(asynchronous) I/O事例:

/*
* IoByEvnt.c
*
* Sample code for Multithreading Applications in Win32
* This is from Chapter 6, Listing 6-2
*
* Demonstrates how to use event objects instead of
* file handles to signal multiple outstanding
* overlapped operation 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
//
int QueueRequest(int nIndex, DWORD dwLocation, DWORD dwAmount);
void CheckOsVersion(); //
// Global variables
// // Need to keep the events in their own array
// so we can wait on them.
HANDLE ghEvents[MAX_REQUESTS];
// 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 main()
{
int i;
BOOL rc;
char szPath[MAX_PATH]; CheckOsVersion(); 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;
} 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.
MTVERIFY( WaitForMultipleObjects(
MAX_REQUESTS, ghEvents, TRUE, INFINITE
) != WAIT_FAILED ); // Describe what just happened.
for (i=0; i<MAX_REQUESTS; i++)
{
DWORD dwNumread; rc = GetOverlappedResult(
ghFile,
&gOverlapped[i],
&dwNumread,
FALSE
);
/************************************************************************/
/*调用GetOverlappedResult(),你获得的结果和“调用ReadFile()或WriteFile()而没有
指定overlapped I/O”所返回的东西一样,这个函数的价值在于,在文件操作真正完成之前,
你不可能确实知道它是否成功。
如果overlapped操作成功,此函数传回TRUE,失败则传回FALS。
如果GetOverlappedResult(,,, BOOL bWait)中的bWait为FALSE而overlapped还是没有完成,
GetLastError()返回ERROR_IO_INCOMPLETE. */
/************************************************************************/
printf("Read #%d returned %d. %d bytes were read.\n",
i, rc, dwNumread);
CloseHandle(gOverlapped[i].hEvent);
} CloseHandle(ghFile); getchar();
return EXIT_SUCCESS;
} /*
* Call ReadFile to start an overlapped request.
* Make sure we handle errors that are recoverable.
* Properly set up the event object for this operation.
*/
int QueueRequest(int nIndex, DWORD dwLocation, DWORD dwAmount)
{
int i;
BOOL rc;
DWORD dwNumread;
DWORD err; MTVERIFY(
ghEvents[nIndex] = CreateEvent(
NULL, // No security
TRUE, // Manual reset - extremely important!
FALSE, // Initially set Event to non-signaled state
NULL // No name
)
);
gOverlapped[nIndex].hEvent = ghEvents[nIndex];
gOverlapped[nIndex].Offset = dwLocation; for (i=0; i<MAX_TRY_COUNT; i++)
{
rc = ReadFile(
ghFile,
gBuffers[nIndex],
dwAmount,
&dwNumread,
&gOverlapped[nIndex]
); // Handle success
if (rc)
{
printf("Read #%d completed immediately.\n", nIndex);
return TRUE;
} err = GetLastError(); // Handle the error that isn't an error. rc is zero here.
if (err == ERROR_IO_PENDING)
{
// asynchronous i/o is still in progress
printf("Read #%d queued for overlapped I/O.\n", nIndex);
return TRUE;
} // 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("ReadFile 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, "IoByEvnt must be run under Windows NT.\n");
exit(EXIT_FAILURE);
} }

MtVerify.h头文件见-----win32多线程-新版本MtVerify.h

win32多线程-异步(asynchronous) I/O的更多相关文章

  1. win32多线程-异步过程调用(asynchronous Procedure Calls, APCs)

    使用overlapped I/O并搭配event对象-----win32多线程-异步(asynchronous) I/O事例,会产生两个基础性问题. 第一个问题是,使用WaitForMultipleO ...

  2. [.net 面向对象程序设计进阶] (19) 异步(Asynchronous) 使用异步创建快速响应和可伸缩性的应用程序

    [.net 面向对象程序设计进阶] (19) 异步(Asynchronous) 使用异步创建快速响应和可伸缩性的应用程序 本节导读: 本节主要说明使用异步进行程序设计的优缺点及如何通过异步编程. 使用 ...

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

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

  4. 可扩展多线程异步Socket服务器框架EMTASS 2.0 (转自:http://blog.csdn.net/hulihui)

    可扩展多线程异步Socket服务器框架EMTASS 2.0 (转自:http://blog.csdn.net/hulihui) 0 前言 >>[前言].[第1节].[第2节].[第3节]. ...

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

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

  6. Android 多线程 异步加载

    Android 应用中需要显示网络图片时,图片的加载过程较为耗时,因此加载过程使用线程池进行管理, 同时使用本地缓存保存图片(当来回滚动ListView时,调用缓存的图片),这样加载和显示图片较为友好 ...

  7. C# 实现的多线程异步Socket数据包接收器框架

    转载自Csdn : http://blog.csdn.net/jubao_liang/article/details/4005438 几天前在博问中看到一个C# Socket问题,就想到笔者2004年 ...

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

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

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

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

随机推荐

  1. APN与VPDN的主要区别

    VPDN APN 安全性 二次认证,加密 一次认证,没有加密 企业成本 高 低 对GGSN要求 可接受动态配置LNS参数信息,对GGSN性能影响小. 静态配置GRE隧道参数,性能影响较大,部分厂家对G ...

  2. Visual Studio Community 2013 中文语言包-离线安装版

    vs_langpack.exe /layout 命令运行或者批处理运行. 转自:http://www.tuicool.com/articles/uMzqAnA 现成安装包下载地址:链接: http:/ ...

  3. iis 在站点中新建虚拟目录站点之后,虚拟目录中的 web.config 与 主站点中的 web.config冲突解决方案

    在虚拟目录站点中增加如下配置即可:<clear/>

  4. QT win 安装配置

    QT windows 版安装配置 安装包:链接:https://pan.baidu.com/s/1LCj2V3xQ1wB9_7zmE5tV6Q 密码:bn9r 首先安装QT Creator 双击安装文 ...

  5. postman-3http请求

    http消息是服务器和客户端之间交换数据的方式. 有2种类型的消息: 请求:由客户端发送用来触发服务器的动作. 响应:来自服务器的应答. https://developer.mozilla.org/z ...

  6. Solr-DIH建立索引并执行简单初步的查询

    我们将solr的安装目录设置为$SOLR_INSTALL,   ./solr start,不使用任何原有的examples来进行,启动完成后,不存在任何的core,提示No cores availab ...

  7. IDA python使用笔记

    pattern='20 E5 40 00' addr=MinEA() for x in range(0,5):     addr=idc.FindBinary(addr,SEARCH_DOWN,pat ...

  8. python + docker, 实现天气数据 从FTP获取以及持久化(二)-- python操作MySQL数据库

    前言 在这一节中,我们主要介绍如何使用python操作MySQL数据库. 准备 MySQL数据库使用的是上一节中的docker容器 “test-mysql”. Python 操作 MySQL 我们使用 ...

  9. 短信发送接口demo

    public class SendValidCode { // 短信发送的接口网关 private static String sendUrl = "******************** ...

  10. [原创]Spring Boot + Mybatis 简易使用指南(一)基础环境搭建

    前言 作者: Ant QQ:517377100 相对于使用JdbcTemplate,Mybatis可自动建立pojo类型与数据库列的映射关系,数据库访问层的开发简单了许多 所有数据库访问操作,均封装在 ...