zoukankan      html  css  js  c++  java
  • DotNet中异步编程(APM)的研究2三种聚集方式rendevousing

    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();

         }

    }

  • 相关阅读:
    Pyhton入门 笔记 第二天 变量与运算符
    Pyhton入门 笔记 第一天 数据类型
    HTML 中的特殊字符
    Extjs--12种布局方式
    .NET easyUI tree树状结构
    SqlServer中嵌套事务使用--事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配 --根本问题
    事务回滚 DEMO
    SQL 事物回滚
    一步一步教你玩转.NET Framework的配置文件app.config
    C# tostring() 方法
  • 原文地址:https://www.cnblogs.com/zguosir/p/877296.html
Copyright © 2011-2022 走看看