• APM(异步编程模型)聚集技巧之等待直至完成聚集技巧


    APM(异步编程模型)支持三种聚集技巧:等待直至完成,轮询和方法回调。

    下面我们先来看看等待直至完成聚集(wait-until-done)技巧:

             我们为了启动一个异步操作,我们可以调用一些BeginXXXfangfa 。所有这些方法都会将请求操作排队,然后返回一个IAsyncResult对象来标识挂起的操作。为了获取操作的结果,我们可以以IAsyncResult对象为参数调用相应的EndXXX方法。根据记录,所有的EndXXX方法都可以接受一个IAsyncResult作为它的一个参数。我们可以看一个EndRead方法:

    Int32 EndRead(IAsyncResult asyncResult)

    注意:EndRead方法的唯一一个参数就是IAsyncResult。但是,更重要的一点就是EndRead方法的返回值是Int32类型,与Read方法的返回值相同。当EndRead方法返回时,它返回从FileStream对象中所读取的字节的数量。

             下面,我们来看一个小例:

    public static void Main(string[] args)

           {

               //打开指示异步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);

     

               // 在这里可以执行一些代码,看个人需求,稍后会分析为什么

               // 挂起该线程直至异步操作结束并获得结果

               Int32 bytesRead = fs.EndRead(ar);

               fs.Close();

     

               Console.WriteLine("字节数是:{0}", bytesRead);

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

               Console.ReadLine();

           }

     

    我在自己的机器上得到的结果:

    字节数是:82

    20-0D-0A-43-3A-5C-47-52-4C-44-52-3D-D2-BB-BC-FC-BB-B9-D4-AD-20-47-68-6F-73-74-20-76-31-31-2E-30-20-0D-0A-5B-62-6F-6F-74-20-6C-6F-61-64-65-72-5D-0D-0A-74-69-6D-65-6F-75-74-3D-33-0D-0A-5B-6F-70-65-72-61-74-69-6E-67-20-73-79-73-74-65-6D-73-5D-0D-0A

     

    如代码所示,该程序没有有效地利用APM。该程序在调用一个BeginXXX方法之后立即调用了一个EndXXX方法,这样做有点笨,因为调用线程进入了睡眠状态,在等待操作的完成,如果希望异步执行该操作,可以调用一个Read方法,这样做效率更高。

             但是在BeginXXXEndXXX方法之间放入一些代码,会看到APM的一些价值,因为这些代码可以在读取文件字节的过程中执行。下面的代码对前面的程序进行了实质性的修改。新版本的程序可以同时执行从多个流中读取数据。在这个例子中,使用FileStream对象,但是该代码可以在所有的派生至Stream的对象上工作,因此它可以从多个文件、套接字甚至串口中同时读取字节。为了支持这些功能,我们必须使用自己编写的AsyncStreamRead类,并将指定的参数传递给AsyncStreamRead的构造器。

           private static void ReadMultipleFiles(params String[] pathnames)

           {

               AsyncStreamRead[] asrs = new AsyncStreamRead[pathnames.Length];

               for (Int32 n = 0; n < pathnames.Length; n++)

               {

                    Stream stream = newFileStream(pathnames[n], FileMode.Open, FileAccess.Read, FileShare.Read, 1024,FileOptions.Asynchronous);

     

                    asrs[n] = new AsyncStreamRead(stream,100);

               }

               for (Int32 n = 0; n < asrs.Length; n++)

               {

                    Byte[] bytesRead =asrs[n].EndRead();

     

                    Console.WriteLine("读取的字节数为:{0}",bytesRead.Length);

                    Console.WriteLine(BitConverter.ToString(bytesRead));

               }

           }

     

           private sealed class AsyncStreamRead

           {

               private Stream m_stream;

               private IAsyncResult m_ar;

               private Byte[] m_data;

               public AsyncStreamRead(Stream stream, Int32 numBytes)

               {

                    m_stream = stream;

                    m_data = new Byte[numBytes];

     

                    //Stream对象初始化一个异步读操作

                    m_ar = stream.BeginRead(m_data,0, numBytes, null, null);

               }

     

               public Byte[] EndRead()

               {

                    Int32 numBytesRead =m_stream.EndRead(m_ar);

                    m_stream.Close();

                    Array.Resize(ref m_data,numBytesRead);

     

                    return m_data;

               }

           }

        上述代码同时执行所有的读操作时,将非常的高效,但该代码还存在一些效率低下的地方。在将所有的读请求排队后,ReadMultipleFiles方法进入第二轮循环,在这轮循环中,ReadMultipleFiles方法按照请求生成的次序为每个流调用EndRead方法。这种方式效率不高,因为不同的流需要不同的时间来读取数据。因此,有可能第二个流中的数据会在第一个流中的数据之前被读取完成。理想情况下,如果发生了这种情况,我们希望首先处理第二个流中的数据,然后在第一个流中的数据读取完成时再处理它。APM确实允许我们实现这一点,但没有采用此处讨论的等待直至完成聚集技巧。

      我的个人官网: www.shuonar.com

  • 相关阅读:
    java 集合Map
    java 集合Collection
    Python 列表生成式, 迭代器&生成器,Json&pickle数据序列化
    Python 函数
    Python列表,字典,元组,字符串操作,文件操作,字符编码
    python的输入输出与循环
    通过数据流发送接收图片
    php中变量的详细介绍
    php数组循环的三种方式
    php session访问限制
  • 原文地址:https://www.cnblogs.com/shuonar/p/3118277.html
Copyright © 2020-2023  润新知