《CLR via C#》读书笔记-异步编程(二)

来源:互联网 发布:西安企业预算软件 编辑:程序博客网 时间:2024/06/11 18:54

在《CLR via C#》的27.2小节中使用了命名管道的内容,上一篇是一个使用命名管道的例子,在《CLR via C#》中同样有一个命名管道的例子(使用异步),具体内容如下:
服务器端的代码:

internal sealed class PipeServer{    //声明一个命名管道    private readonly NamedPipeServerStream m_pipe = new NamedPipeServerStream(        "Echo",PipeDirection.InOut,-1,PipeTransmissionMode.Message,        PipeOptions.Asynchronous|PipeOptions.WriteThrough);    public PipeServer(){        m_pipe.BeginWaitForConnection(    }    //定义当客户端连接后的回调方法    private void ClientConnected(IAsyncResult result){        new PipeServer();        //APM的结束        m_pipe.EndWaitForConnection(result);        byte[] data = new byte[1000];        m_pipe.BeginRead(data,0,data.length,GotRequest,data);    }    //当数据读取完毕后的回调方法    private void GotRequest(IAsyncResult result){        //EndRead方法返回已经读取内容的字节数。若返回值为零,则代表到达流的末尾        int bytesread=m_pipe.EndRead(result);        byte[] data=(byte[])result.AsyncState;        data=Encoding.UTF8.GetBytes(            Encoding.UTF8.GetString(data,0,bytesread).ToUpper().ToCharArray());        m_pipe.BeginWrite(data,0,data.Length,WriteDone,null);    }    private void WriteDone(IAsyncResult result){        m_pipe.EndWrite(result);        m_pipe.Close();    }}

通过上面的这个例子,可以看到APM(Asynchronous Programming Model)的编写模式,在方法的内部,以Endxxx为开始,以BeginXXX为结束,在两者之间是相关的内容处理。
参数说明
对BeginXXX中方法的参数说明:方法的前三个参数是正常的,第四个参数是AsyncCallback,该委托的定义如下:

public delegate void AsyncCallback(IAsyncResult ar)

可以将IAsyncResult看成是IRP的唯一标示。其唯一标示了一个I/O请求,系统在将请求放入驱动程序的队列中,并返回IAsyncResult对象的一个引用。
IAsyncResult是一个接口,而该接口具有几个属性,而实现了该接口的类也一定会存在这几个属性。这几个属性的具体定义如下:
属性
IAsyncResult的AsyncState就可以用于数据传输,由beginxxx传入到endxxx中。下面是客户端的代码

internal sealed class PipeClient{    private readonly NamedPipeClientStream m_pipe;    public PipeClient(string serverName,string message)    {        m_pipe=new NamedPipeClientStream(serverName,"Echo",PipeDirection.Inout,PipeOptions.Asynchronous|PipeOptions.WriteThrough);        m_pipe.Connect();        //必须先连接,之后才能设定ReadMode        m_pipe.ReadMode=PipeTransmissionMode.Message;        byte[] output=Encoding.UTF8.GetBytes(message);        m_pipe.BeginWrite(output,0,output.Length,WriteDone,null);    }    private void WriteDone(IAsyncResult result){        m_pipe.EndWrite(result);        byte[] data=new byte[1000];        m_pipe.BeginRead(data,0,data.Length,GotResponse,data);    }    private void GotResponse(IAsyncResult result){        int bytesRead = m_pipe.EndRead(result);        byte[] data=(byte[])result.AsyncState;        Console.WriteLine("服务器的返回值"+Encoding.UTF8.GetString(data,0,data.Length));        m_pipe.Close();    }}

如何使用服务器端和客户端的程序
使用服务器端的代码如下:

public static void Main(){    for(int i=0;i<Environment.ProcessorCount;i++){        new PipeServer();    }    Console.WriteLine("回车结束服务器程序");    Console.ReadLine();}

使用客户端的代码如下

public static void Main(){    for(int i=0;i<100;i++)        new PipeClient(".","请求"+i);    Console.ReadLine();}

以上的代码均来自《CLR via C#》的27.2小节。代码很简单,抄录很麻烦。肩膀都酸了。
小节
APM与其他正常的代码没有任何的差别,不管是异常处理还是其他方面,基本上一模一样。只有一个例外,就是在使用beginxxx和endxxx时略有差别。与多线程相比较,基本上没有什么太大的花样。
在27.2的开头,反而是讲了APM的关键信息
1、所有派生自system.io.stream并与硬件通信的类(包括filestream和networkstream)都提供APM
2、system.net.dns类提供了几个方法
3、system.net.sockets.socket类中提供符合APM编程方式的方法
另外,所有委托都定义了一个begininvoke方法。
总的来说,APM编码方式是一种考虑了系统稳定性的编码方式。其作用是让系统更加稳定。与正常使用的方法没有多大的差别。

0 0
原创粉丝点击