惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

罗磊的独立博客
Martin Fowler
Martin Fowler
J
Java Code Geeks
The GitHub Blog
The GitHub Blog
C
Check Point Blog
H
Help Net Security
Google DeepMind News
Google DeepMind News
人人都是产品经理
人人都是产品经理
博客园 - 聂微东
P
Proofpoint News Feed
V
Visual Studio Blog
Stack Overflow Blog
Stack Overflow Blog
雷峰网
雷峰网
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Vercel News
Vercel News
S
SegmentFault 最新的问题
L
LangChain Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
The Cloudflare Blog
Hugging Face - Blog
Hugging Face - Blog
有赞技术团队
有赞技术团队
博客园_首页
小众软件
小众软件
aimingoo的专栏
aimingoo的专栏

博客园 - zguosir

[转载]转给自己的,跨业洗牌 [转载]挖一口属于自己的井 MSIL探索-IL介绍 MSIL探索-序 DotNet中异步编程(APM)的研究3-代理与异步编程 我的简历 我的技术特长 我的项目-物业收费 我的项目-人员定位 我的项目-证券分析 我的项目-工作票管理 我的项目-地衡读数 我的项目-物业管理(大厦版) 我的项目-财务系统 我的项目-图形拼接 我的项目-磁盘考试系统 我的项目-通用题库系统 收藏列表 DotNet中异步编程(APM)的研究1-异步编程介绍
DotNet中异步编程(APM)的研究2-三种聚集方式rendevousing
zguosir · 2007-08-31 · via 博客园 - zguosir

DotNet中异步编程(APM)的研究2
三种聚集方式rendevousing (by zguosir/gshzheng)
这个名字挺拗口,其实就是如何知道异步操作结束

异步操作结束后,CLR将自动地

l           设置IAsyncResult对象的IsCompleteTrue

l           IAsyncResultAsyncWaitHandled对象设上信号;

l           如果设置了回调函数,则调用它。

程序有三种方式可以获知异步操作是否已经执行完成,我们称之为聚集技巧(Rendezvous Techniques)。等待直到完成(wait-until-done)、轮询(polling)和回调方法(callback)。选择哪一个依赖于程序是否有当异步操作执行完毕后要执行的指令。(实际中,最常用的是回调方法)

1.等待直到完成

调用线程启动一个异步操作后将被挂起,直到异步操作结束。在这种方式下,所谓的异步操作从执行效果上看就相当于其对应的同步操作了。有两种方式可以挂起当前调用线程,等待异步操作的完成。

l           直接调用EndOperation()方法,等待执行结果;

l           使用IAsyncResult对象AsnycWaitHandle.WaitOne()方法来等待。

下面的例子演示了用第一种方式通过异步操作从读取文件内容:

Example1

public class WaitUntilDone0

{

     public static void ReadFileAsync()

     {

         //打开文件并指定异步操作

         FileStream fs=new FileStream(@"c:\apm.txt",FileMode.Open,

FileAccess.Read,FileShare.Read,1024,true);

         //开启异步读取

         byte[] data = new byte[100];

         IAsyncResult ar = fs.BeginRead(data,0,data.Length,null,null);

         //执行某些代码...

         try

         {

              //等待直到异步读取完成,并结束异步操作

              int cnt = fs.EndRead(ar);

              fs.Close();

              Console.WriteLine(BitConverter.ToString(data,0,cnt));

         }

         catch(Exception e)

         {

              Console.WriteLine(e.Message);

         }

     }

}

下面的例子演示了第二种方式,利用异步操作从读取文件内容:

Example2

//开启异步读取

byte[] data = new byte[100];

IAsyncResult ar = fs.BeginRead(data,0,data.Length,null,null);

//执行某些代码...

//等待直到异步读取完成

ar.AsyncWaitHandle.WaitOne();

try

{

     //结束异步操作,并得到结果

     int cnt = fs.EndRead(ar);

     fs.Close();

}

上面两个程序并没有有效的利用APM,因为在BeginRead()之后,我们就立即调用了EndRead()(或WaitOne())方法,调用线程挂起进入了休眠状态,等待操作完成。在实际应用中,如果在BeginReadEndRead之间放入一些代码,或者对这两个函数的调用分配在不用的方法调用中,就会体现APM的价值了。

这两种方法的区别就是Example2中将等待与结束异步操作分离开了

2.轮询polling

使用轮询技巧,程序在开启异步操作后不需要等待其执行完毕,而可以干其它的事情。当在某次检查IAsyncResultIsComplete属性为true时,即可知道操作已完成,调用EndOperation()得到其结果。Example3是用轮询技巧来完成异步读文件的功能:

Example3

//开启异步读取

byte[] data = new byte[100];

IAsyncResult ar = fs.BeginRead(data,0,data.Length,null,null);

//执行某些代码...

//不停查询异步操作执行的状态,直到执行完毕

while(!ar.IsCompleted)

{

     //刷新用户界面

     Console.Write(".");

     Thread.Sleep(10);

}

Console.WriteLine();

try

{

     //结束异步操作,并得到结果

     int cnt = fs.EndRead(ar);

     fs.Close();

}

本例中,为了简单的目的,直接在调用了BeginRead()后,就开始循环查询了,实际编写使用轮询技巧的代码时,一般是让单独的线程定期地来查询异步操作是否结束。

3.回调callback

在构建高性能和可扩展的应用程序架构时,回调方法是最好用的聚集技巧。它在任何时候都不用将调用线程挂起等待,也不会需要另外的不定期的检查操作是否完成。

回调方法是一个符合AsyncCallBack签名的方法,在调用开启异步操作时,将回调方法传入BeginOperation()。当异步操作执行完毕后,将自动调用这个方法,在这个方法中调用EndOperation()得到执行的结果。

Example4

public class Callback

{

     //class-scope定义缓冲区

     private static byte[] data=null;

     public static void cb_read(IAsyncResult ar)

     {

         FileStream fs= ar.AsyncState as FileStream;

         try

         {

              //结束异步操作,并得到结果

              int cnt = fs.EndRead(ar);

              fs.Close();

              Console.WriteLine(BitConverter.ToString(data,0,cnt));

         }

         catch(Exception e)

         {

              Console.WriteLine("An exception occurred while processing :{0}",e.Message);

         }

     }

     public static void ReadFileAsync()

     {

         //打开文件并指定异步操作

         FileStream fs=new FileStream(@"c:\apm.txt",FileMode.Open,

FileAccess.Read,FileShare.Read,1024,true);

         //开启异步读取

         data = new byte[100];

         IAsyncResult ar = fs.BeginRead(data,0,data.Length,new AsyncCallback(cb_read),fs);

         //执行某些代码...

         Console.ReadLine();

     }

}