您的位置:首页 > 编程语言 > C#

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

2016-11-24 22:40 417 查看
在《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编码方式是一种考虑了系统稳定性的编码方式。其作用是让系统更加稳定。与正常使用的方法没有多大的差别。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐