当前位置: 首页 > 编程日记 > 正文

异步操作(三)

APM的轮询聚焦技巧

就从字面意思来理解,每隔一段时间来查询,异步操作的结果。而怎么实现轮询的方法了,这里就要谈到IAsyncResult接口。它定义了若干个只读属性

public interface IAsyncResult
{
Object AsyncState {
get;}
WaitHandle AsyncWaitHandle {
get;}
Boolean IsCompleted {
get;}
Boolean CompletedSynchronously {
get;}
}

其中最常用的属性是AsyncState。使用轮询聚集技巧时,要使用AsyncWaitHandle和IsCompleted属性。而对于CompletedSynchronously属性,有时侯供实现BeginXxx和EndXxx方法的开发人员查询。其实轮询的效率不高,编写轮询聚集技巧的代码时,要让一个线程定期地询问CLR来查看异步请求是否已经完成运行。实质上是浪费了一个线程的时间。

下面是一个轮询聚集技巧的示例:

public static void PollingWithIsCompleted()
{
FileStream fs
=new FileStream(@”C:\Boot.ini”,FileMode.Open,FileAccess.Read,
FileShare.Read,
1024,FileOptions.Asynchronous);
Byte[] data
=new Byte[100];

//为FileStream对象初始化一个异步读操作
IAsyncResult ar=fs.BeginRead(data,0,data.Length,null,null);

//每隔10秒查询一次是否操作已经完成
while(!ar.IsCompleted)
{
Console.WriteLine(“Operation not completed;still waiting.”);
Thread.Sleep(
10);
}

//获取结果。注意:EndRead方法不能挂起这个线程 因为前面那个循环已经确定操作完成了
Int32 bytesRead=fs.EndRead(ar);

fs.Close();

//显示结果
….
}

上面是通过IAysncResult的IsCompleted属性来判断一个操作是否完成,下面是通过AsyncWaitHandle属性,它返回一个派生自WaitHandle的对象的引用,该对象通常为System.Threading.ManualResetEnent.

public static void PollingWithAsyncWaitHandle()
{
//打开指示异步I/O操作的文件
FileStream fs=new FileStream(@”C:\Boot.ini”,FileMode.Open,FileAccess.Read,
FileShare.Read,
1024,FileOptions.Asynchronous);
Byte[] data
=new Byte[100];

//为FileStream对象初始化一个异步读操作
IAsyncResult ar=fs.BeginRead(data,0,data.Length,null,null);

//与上面例子效果相同
While(!ar.AsyncWaitHandle.WaitOne(10,false)
{
Console.WriteLine(“Operation not completed;still waiting.”);
}

//获取结果。注意:EndRead方法不能挂起这个线程 因为前面那个循环已经确定操作完成了
Int32 bytesRead=fs.EndRead(ar);

fs.Close();

//显示结果
….

}

APM方法回调聚集技巧

在所有ARM聚集技巧中,构建性能和扩展的应用程序框架时,方法回调聚集技巧最好用。该技巧不会将一个线程置于等待状态,而且该技巧还不会定期地检查异步操作是否完成而浪费CPU时间。

首先将异步I/O请求排队等候,然后线程继续执行它希望执行的任何事情。接着当 I/O请求完成时,Windows将工作项加入CLR的线程池的队列中。最后,线程池中的线程将工作项从队列中取出,并调用我们编写的一些方法(通过这种方式我们可以知道异步I/O操作已经完成)。现在回调内部,我们首先调用EndXxx方法来获得异步操作的结果,然后就可以自由的继续处理结果。当回调方法返回时,线程池中的线程返回到线程池中准备服务下一个排队的工作项。

public static class Program
{
//将数组声明为static,以便Main方法和ReadIsDone方法可访问它
private static Byte[] s_data=new Byte[100];

public static void Main()
{
Console.WriteLine(“Main thread ID
={0}”,Thread.CurrentThread.ManagedThreadId);

//打开指示异步I/O操作的文件
FileStream fs=new FileStream(@”C:\Boot.ini”,FileMode.Open,FileAccess.Read,
FileShare.Read,
1024,FileOptions.Asynchronous);

//为FileStream对象初始化一个异步读操作,并将FileStream对象fs传递给回调方法ReadISDone
fs.BeginRead(s_data,0,s_data.Length,ReadIsDone,fs);

//在这里执行一些其他代码将非常有用…..

//出于演示目的,将主线程挂起
Console.ReadLine();

}

private static void ReadIsDone(IAsyncResult ar)
{
//显示正在执行ReadIsDone方法线程的ID
Console.WriteLine(“ReadIsDone thread Id={0}”,
Thread.CurrentThread.ManagedThreadID

//从IAsyncResult对象中提取FileStream对象
FileStream fs=(FileStream)ar.AsyncState;

//获取结果
Int32 bytesRead=fs.EndRead(ar);

//已经没有操作执行任务,关闭文件
fs.Close();

//显示结果
}
}

因为这里ReadIsDone函数,要通过全局变量才能访问到读取到的数据。都写到Main函数当中去。还有就是要将回调方法名称传递给BeginRead函数以及FileStream对象实例也要传递给该函数(目的通过这种方式将FileStream对象实例传递到了回调方法中)。当然这里可以利用C#匿名方法特征,就不存在这个问题了。

public static void Main()
{
Console.WriteLine(“Main thread ID
={0}”,Thread.CurrentThread.ManagedThreadId);

//打开指示异步I/O操作的文件
FileStream fs=new FileStream(@”C:\Boot.ini”,FileMode.Open,FileAccess.Read,
FileShare.Read,
1024,FileOptions.Asynchronous);
Byte[] data
=new Byte[100];


//为FileStream对象初始化一个异步读操作,并将FileStream对象fs传递给回调方法ReadISDone
fs.BeginRead(s_data,0,s_data.Length,delegate(IAsyncResult ar)
{
//显示正在执行ReadIsDone方法线程的ID
Console.WriteLine(“ReadIsDone thread Id={0}”,
Thread.CurrentThread.ManagedThreadID

//获取结果
Int32 bytesRead=fs.EndRead(ar);

//已经没有操作执行任务,关闭文件
fs.Close();

//显示结果

},
null);

//出于演示目的,将主线程挂起
Console.ReadLine();
}

还记得异步操作(二)中最后一个多流读取文件的例子吗,这里改为回调聚集技巧,那么程序效率又得到进一步提高

private static void ReadMultipleFiles(params String[] pathnames)
{
for(Int32 n=0;n<pathname.Length;n++)
{
//打开指示异步I/O操作文件
Sream stream=new FileStream(pathnames[n],FileMode.Open,FileAccess.Read,
FileShare.Read,
1024,FileOptions.Asynchronous);

//为Stream 对象初始化一个异步操作
new AsyncStreamRead(stream,100,delegate(Byte[] data
{
//处理数据

});
}

//所有的流都已经打开了,而且所有的读请求都已经排队;他们同时并发执行,
//而且他们结束时它们将被处理

//主线程可以在这里做一些其他工作,如果愿意的话

//处于演示目的,将主线程挂起来
Console.ReadLine();

}
}

//定义一个委托
private delegate void StreamBytesRead(Byte[] streamData);

private sealed class AsyncSreamRead
{
private Stream m_stream;
private Byte[] m_data;
StreamBytesRead m_callback;

public AsyncStreamRead(Stream stream,Int32 numBytes,StreamByteRead callback)
{
m_stream
=stream;
m_data
=new Byte[numBytes];
m_callback
=callback;

stream.BeginRead(m_data,
0,numBytes,ReadIsDone,null);
}

//当IO操作结束时调用下述方法
private void ReadIsDone(IAsyncResult ar)
{
Int32 numByteRead
=m_stream.EndRead(ar);

m_stream.Close();

//调整数据大小以节省空间
Array.Resize(ref m_data,numBytesRead);

//调用应用程序的回调方法(注意这里调用的方法是个匿名方法 )
m_callback(m_data);
}
}

使用APM执行受计算限制的异步操作

先看一个简单的程序

private static UInt64 Sum(UInt64 n)
{
UInt64 sum
=0;
for(UInt64 i=1;i<=n;i++)
{
//检查是否益处,是就抛出一个异常
Checked
{
sum
+=I;
}
}
return sum;
}

如果这里n非常大,Sum方法将需要很长时间来执行。那么这里也用异步操作来完成

internal delegate UInt64 SumDelegate(UInt64 n);

这里定义委托,据委托揭秘可知,在编译器里面实际的内容

internal sealed class SumDelegate:MulticastDelegate
{
public SumDelegate(Object object,IntPtr method);
public UInt64 Invoke(UInt64 n);
pulbic IAsyncResult BeginInvoke(UInt64 n,AsyncCallback Callback,Object
object);
public UInt64 EndInvoke(IAsyncResult result);
}

相信看到这段代码,就应该会写后面的程序了:

public static void Main()
{
SumDelegate sumDelegate
=Sum;
//调用线程池线程
sumDelegate.BeginInvoke(100000000,SumIsDone,sumDelegate);
Console.ReadLine();
}

这里说明一下委托的BeginInvoke方法通过内部调用ThreadPool的QueueUserWorkItem将受限制的操作加入到CLR线程池的队列中。最后,BeginInvoke方法将IAsyncResult对象返回到它的调用者。调用者在执行异步I/O操作时就可以使用这个IAsyncResult对象了。因为BeginInvoke方法将操作加入线程池的队列,所以线程池中的线程将被唤醒,将工作项从队列中取出,然后调用受计算限制的操作。线程池中的线程从执行方法的过称中返回时,线程就返回到线程池。但是本例方法中有SumIsDone,那么该线程就会调用SumIsDone方法。即完成回调。

private static void SumIsDone(IAsyncResult)
{
//从IAsyncResult对象中提取SumDelegate对象
SumDelegate sumDelegate=(SumDelegate)ar.AsyncState;
//获取结果
UInt64 sum=sumDelegate.EndInvoke(ar);
//显示结果
Console.WriteLine(“Sum={0}”,sum);
}

转载于:https://www.cnblogs.com/30ErLi/archive/2010/09/19/1830709.html

相关文章:

Django-C002-深入模型,到底有多深

此文章完成度【100%】留着以后忘记的回顾。多写多练多思考&#xff0c;我会努力写出有意思的demo&#xff0c;如果知识点有错误、误导&#xff0c;欢迎大家在评论处写下你的感想或者纠错。 ORM介绍&#xff1a;对象关系映射&#xff08;英语&#xff1a;(Object Relational Map…

Linux中断流程分析

裸机中断&#xff1a; 1、中断流入口 2、事先注册中断处理程序 3、根据中断源编号&#xff0c;调取处理程序 irq_svc&#xff1a;1、等到产生中断源的编号&#xff08;每一个中断号都有一个描述结构&#xff09; 2、转载于:https://www.cnblogs.com/sanshijvshi/p/8531025.html…

手把手视频第二节

一、单片机的三大内部资源&#xff08;我们作为用户&#xff0c;单片机可以提供给我们的资源&#xff09; 1、FALSH&#xff08;程序存储空间&#xff09; &#xff08;1&#xff09;早期使用的一般是TOPROM &#xff0c;程序只能写入一次&#xff0c;程序写错了只能换一块。 &…

SQL Server DATEADD() 函数

定义和用法 DATEADD() 函数在日期中添加或减去指定的时间间隔。 语法 DATEADD(datepart,number,date) date 参数是合法的日期表达式。number 是您希望添加的间隔数&#xff1b;对于未来的时间&#xff0c;此数是正数&#xff0c;对于过去的时间&#xff0c;此数是负数。 datepa…

致广大关注《网络规划设计师考试案例梳理、真题透解与强化训练》读者朋友的一封信...

致广大关注《网络规划设计师考试案例梳理、真题透解与强化训练》读者朋友的一封信 书是人类进步的阶梯&#xff0c;读书是增强个人软实力的佳径。好读书是你的美德&#xff0c;读好书是你的选择&#xff0c;书好读是我们的承诺&#xff01;如果有心&#xff0c;不妨把一卷《网络…

Mac MySQL 数据库配置(关系型数据库管理系统)

本文已停止更新&#xff0c;点击此链接查看本文最新内容 &#xff01;&#xff01;&#xff01;前言 MySQL 关系型数据库管理系统。1、配置准备工作 1&#xff09;配置数据库准备工作 下载相关软件 mysql-5.7.21-1-macos10.13-x86_64.dmgmysql-workbench-community-6.3.10-maco…

SSM框架——Spring+SpringMVC+Mybatis的搭建教程

一&#xff1a;概述SSM框架在项目开发中经常使用到&#xff0c;相比于SSH框架&#xff0c;它在仅几年的开发中运用的更加广泛。 Spring作为一个轻量级的框架&#xff0c;有很多的拓展功能&#xff0c;最主要的我们一般项目使用的就是IOC和AOP。SpringMVC是Spring实现的一个Web层…

【java】兴唐课程第五节到第九节知识点总结

第九节 1、 代码&#xff1a;void readBook(String… bookNames) 表示不确定参数的个数&#xff0c;此时变量为一个数组。 2、当方法中的参数名称(如stuname)和属性名称相同时。 this.stuname表示属性 stuname表示参数。 3、主方法与所在的累无关&#xff0c;是一个程序的入口…

构建RHEL上的extmail

一、extmail_solutionz 1、ExtMail Solution 结构 ExtMail Solution 是一个基于优秀开源软件的电子邮件系统解决方案&#xff0c;核心部件包括了Postfix、Amavisd-new、ClamAV、ExtMail、ExtMan、Courier系列软件。是一个功能相对比较齐全的免费电子邮件系统。以下是其主要的特…

MapReduce_wordcount

测试数据&#xff1a; [hadooph201 mapreduce]$ more counttext.txt hello mamahello babahello wordcai wen weimama baba jiejie gegegege jiejie didimeimei jiejiedidi mamaayi shushuayi mamahello mamahello babahello wordcai wen weimama baba jiejie gegegege jiejie …

Appium+python自动化(八)- 初识琵琶女Appium(千呼万唤始出来,犹抱琵琶半遮面)- 下(超详解)...

​简介 通过上一篇宏哥给各位小伙伴们的引荐&#xff0c;大家移动对这位美女有了深刻的认识&#xff0c;而且她那高超的技艺和婀娜的身姿久久地浮现在你的脑海里&#xff0c;是不是这样呢&#xff1f;&#xff1f;&#xff1f;不要害羞直接告诉宏哥&#xff1a;是&#xff0c;就…

蜻蜓resin服务器虚拟目录的设置

首先&#xff0c;别急着打开服务器先&#xff0c;接住打开resin主目录下的conf文件夹的resin.conf文件&#xff0c;老规矩&#xff0c;备份先&#xff0c;mv resin.conf resin.conf.bak然后vi resin.conf 文件&#xff0c;找到如下这段代码&#xff1a;1 <!--configures the…

【java】兴唐第十节课知识点总结

1、使用main里的成员方法也要实例化对象吗&#xff1f; 必须实例化 ///重点&#xff01; 2、在成员方法中调用另一个成员方法可以直接调用&#xff08;前面省略一个this.&#xff09; 3、 \n也可以在java里用 4、null可以是除了基本数据类型外的任何数据类型 5、基本数据类…

SharePoint2010是个什么东西

Microsoft SharePoint Foundation is an application that is built on top of Internet Information Services (IIS) and the Microsoft ASP.NET Framework. Microsoft SharePoint Foundation 是架构在IIS和ASP.NET Framework上的一个应用程序。IIS是与互联网站点相关的&#…

Linux Shell高级技巧(目录)

为了方便我们每个人的学习&#xff0c;这里将给出Linux Shell高级技巧五篇系列博客的目录以供大家在需要时参阅和查找。 Linux Shell高级技巧(一) http://www.cnblogs.com/stephen-liu74/archive/2011/12/22/2271167.html一、将输入信息转换为大写字符后再进行条件判断二、为调…

Keras卷积+池化层学习

转自&#xff1a;https://keras-cn.readthedocs.io/en/latest/layers/convolutional_layer/ https://keras-cn.readthedocs.io/en/latest/layers/pooling_layer/ 1.con1D keras.layers.convolutional.Conv1D(filters, kernel_size, strides1, paddingvalid, dilation_rate1, ac…

【Java】阿里巴巴java开发手册总结(我能看懂的)

尽管这本《手册》句句是精华&#xff0c;但由于我还是个菜鸟&#xff0c;这里仅作&#xff08;我能用的到的&&我能看懂的&#xff09;的笔记 1.1命名风格 1、类名用UpperCamelCase的风格 2、方法名、参数名、成员变量、局部变量都统一用lowerCameCase的风格&#xff…

关于maya与max互导FBX出现错误的解决方案。

因为自己实在是不愿意一次又一次把时间浪费在导入导出的问题上。每一次都是多试几次才成功&#xff0c;也没有真正去测试这个东西。但是今天实在是碰到了错误中的极品了。最后还是决定写下来。。算是给自己做笔记吧。。大家如果在导入导出的时候遇到一些问题不妨试试以下几种方…

AS3.0中的显示编程(六)-- 几何结构

几何结构&#xff0c;主要是完成Flash编程中&#xff0c;一些和几何相关的内容。如显示对象的变形角度、公式计算等。可能很多人和我一样&#xff0c;高中学的几何知识&#xff0c;差不多都已经还给老师了。不过也不用太担心&#xff0c;因为一般情况下&#xff0c;我们也用不到…

Win10命令行激活 电脑组装

系统激活&#xff1a; 1. 管理员身份运行 cmd 2. slmgr.vbs /upk //卸载产品密匙 3. slmgr /ipk W269N-WFGWX-YVC9B-4J6C9-T83GX //安装 4. slmgr /skms zh.us.to …

【java】兴唐第十五节课

知识点&#xff1a; 1、定义包名不能以java.为开头。 2、获取系统时间的方法&#xff1a; 注意&#xff1a; &#xff08;1&#xff09; 引入Date类时&#xff0c;引入的是java.util.Date 而不是java.sql.Date(后者是前者的子类)。 代码实现 Date date new Date(); System.o…

SQL Server 日期和时间相关的数据类型有两种

SQL Server 日期和时间相关的数据类型有两种&#xff1a;DateTime和SmallDateTime。 DateTime:需要8个字节&#xff0c;前4个字节用1900年1月1日以后的天数表示日期&#xff0c;后4个字节表示一天中的时间。支持的日期范围&#xff1a;1/1/1753 12:00:00 AM到12/31/9999 11:59…

序列化pickle

import pickle d { name:alex, role:police, blood: 76, weapon:AK47 } d_dump pickle.dumps(d) #序列化 print (pickle.loads(d_dump)) #反序列化 f open(game.pkl, wb) pickle.dump(d, f) #First in first out (FIFO) pickle.dump(alive_players, f) dump 写入文件 du…

T-SQL笔记3:事务、锁定和并发

T-SQL笔记3&#xff1a;事务、锁定和并发 本章摘要 1&#xff1a;事务 1.1&#xff1a;显式事务 1.2&#xff1a;使用DBCC OPENTRAN显示最早的活动事务 2&#xff1a;锁定 2.1&#xff1a;查看锁的活动 3&#xff1a;并发影响及隔离级别 3.1&#xff1a;并发影响 3.2&#xff1…

几种常用数据库比较

目前&#xff0c;商品化的数据库管理系统以关系型数据库为主导产品&#xff0c;技术比较成熟。面向对象的数据库管理系统虽然技术先进&#xff0c;数据库易于开发、维护&#xff0c;但尚未有成熟的产品。国际国内的主导关系型数据库管理系统有Oracle、Sybase、INFORMIX和INGRES…

成功将BlogEngine 1.5 升级到了BlogEngine 2.0

使用BlogEngine.Net博客系统有两年时间了。官方的最新版本已经出到了2.5。但它是基于.net4.0的。也就是说服务器必须安装.net4.0&#xff0c;运行环境必须选择4.0。出于移植性的考虑。我决定将我的博客升级到2.0。BlogEngine.Net2.0是继续.net2.0的。虽说必须安装.net 3.5&…

【java】4.27上课及做作业时遇到的问题及第十六节课笔记整理

注意&#xff1a; 部分知识点只在eclipse运行环境中适用 1、字符串转化为字符数组的方法: 代码实现&#xff1a; char[] strcs text.toCharArray();2、字符数字转化为字符串 String reStr new String(re,0 ,position);3、打包及 引包的方法 &#xff08;1&#xff09; 用ex…

【Android】基于A星寻路算法的简单迷宫应用

简介 基于【漫画算法-小灰的算法之旅】上的A星寻路算法&#xff0c;开发的一个Demo。目前实现后退、重新载入、路径提示、地图刷新等功能。没有做太多的性能优化&#xff0c;算是深化对A星寻路算法的理解。 界面预览: 初始化: 寻路: 后退: 提示: 完成: 刷新地图: 下载地址: 项目…

[转]SQL 约束讲解

约束主要包括&#xff1a; •NOT NULL •UNIQUE •PRIMARY KEY •FOREIGN KEY •CHECK •DEFAULT 1、not null &#xff1a;用于控制字段的内容一定不能为空&#xff08;NULL&#xff09;。 用法 &#xff1a;Create table MyTable ( id …

JSON 转 VO

需求 将获取的json数据直接转为vo 解决 利用net.sf.json.JSONObject的toBean() 确保json中的key值和vo中的字段名称一致 JSONObject jsonObject new JSONObject();UserVO vo new UserVO(); vo (UserVO) net.sf.json.JSONObject.toBean(jsonObject, UserVO.class);参考文档地…