|
| |
名片设计 CorelDRAW Illustrator AuotoCAD Painter 其他软件 Photoshop Fireworks Flash |
|
使用基本类库 为了更好地理解C#与C++的区别和解决问题方法的变化,我们先来看一个比较简朴的例子。我们将创建一个读取文本文件的类,并在屏幕上显示其内容。我将把它做成多线程程序,以便在从磁盘上读取数据时还可以做其他的工作。 在C++中,我们可能会创建一个读文件的线程和另一个做其他工作的线程,这二个线程将各自独立地运行,但可能会需要对它们进行同步。在C#中,我们也可以完成同样的工作,由于.NET框架提供了功能强盛的异步I/O机制,在编写线程时,我们会节省不少的时间。 异步I/O支持是内置在CLR中的,而且几乎与使用正常的I/O流类相同简朴。在程序的开始,我们首先通知编译器,我们将在程序中使用许多名字空间中的对象: usingSystem; usingSystem.IO; usingSystem.Text; 在程序中包含System,并不会自动地包含其所有的子名字空间,必须使用using关健字明确地包含每个子名字空间。我们在例子中会用到I/O流类,因此需要包含System.IO名字空间,我们还需要System.Text名字空间支持字节流的ASCII编码。 由于.NET架构为完成了大部分的工作,编写这一程序所需的步骤相称简朴。我们将用到Stream类的BeginRead方式,它提供异步I/O功能,将数据读入到一个缓冲区中,当缓冲区可以处理时调用相应的处理程序。 我们需要使用一个字节数组作为缓冲区和回叫方式的代理,并将这二者定义为驱动程序类的private成员变量。 publicclassAsynchIOTester { privateStreaminputStream; privatebyte[]buffer; privateAsyncCallbackmyCallBack; inputStream是一个Stream类型的变量,我们将对它调用BeginRead方式。代理与成员函数的指针异常相似。代理是C#的第一类元素。 当缓冲区被磁盘上的文件填满时,.NET将调用被代理的方式对数据进行处理。在等待读取数据期间,我们可以让计算机完成其他的工作。(在本例中是将1个整型变量由1增加到50000,但在实际的应用程序中,我们可以让计算机与用户进行交互或作其他有意义的工作。) 本例中的代理被定义为AsyncCallback类型的过程,这是Stream的BeginRead方式所需要的。System空间中AsyncCallback类型代理的定义如下所示: publicdelegatevoidAsyncCallback(IAsyncResultar); 这一代理可以是与任何返回void类型值、将IAsyncResult界面作为参数的方式相关联的。在该方式被调用时,CLR可以在运行时传递IAsyncResult界面对象作为参数。我们需要如下所示的形式定义该方式: voidOnCompletedRead(IAsyncResultasyncResult) 然后在构造器中与代理连接起来: AsynchIOTester() { ??? myCallBack=newAsyncCallback(this.OnCompletedRead); } 上面的代码将代理的实例赋给成员变量myCallback。下面是全部程序的具体工作原理。在Main函数中,创建了一个类的实例,并让它开始运行: publicstaticvoidMain() { AsynchIOTestertheApp=newAsynchIOTester(); theApp.Run(); } new关健字能够启动构造器。在构造器中我们打开一个文件,并得到一个Stream对象。然后在缓冲中分配空间并与回调机制联结起来。 AsynchIOTester() { inputStream=File.OpenRead(@"C:/MSDN/fromCppToCS.txt"); buffer=newbyte[BUFFER_SIZE]; myCallBack=newAsyncCallback(this.OnCompletedRead); } 在Run方式中,我们调用了BeginRead,它将以异步的方法读取文件。 inputStream.BeginRead( buffer,//存放结果 0,//偏移量 buffer.Length,//缓冲区中有多少字节 myCallBack,//回调代理 null);//本地对象 这时,我们可以完成其他的工作。 for(longi=0;i<50000;i++) { if(i%1000==0) { Console.WriteLine("i:{0}",i); } } 文件读取操作结束后,CLR将调用回调方式。 voidOnCompletedRead(IAsyncResultasyncResult) { 在OnCompletedRead中要做的第一件事就是通过调用Stream对象的EndRead方式找出读取了多少字节: intbytesRead=inputStream.EndRead(asyncResult); 对EndRead的调用将返回读取的字节数。假如返回的数字比0大,则将缓冲区转变为一个字符串,然后将它写到控制台上,然后再次调用BeginRead,开始另一次异步读的过程。 if(bytesRead>0) { Strings=Encoding.ASCII.GetString(buffer,0,bytesRead); Console.WriteLine(s); inputStream.BeginRead(buffer,0,buffer.Length, myCallBack,null); } 现在,在读取文件的过程中就可以作别的工作了(在本例中是从1数到50000),但我们可以在每次缓冲区满了时对读取的数据进行处理(在本例中是向控制台输出缓冲区中的数据)。有爱好的读者可以点击此处下载完整的源代码。 异步I/O的治理完全是由CLR提供的,这样,在网络上读取文件时,会更好些。 在网络上读取文件 在C++中,在网络上读取文件需要有相称的编程技巧,.NET对此提供了广泛的支持。事实上,在网络上读取文件仅仅是基础类库中Stream类的另一种应用。 首先,为了对TCP/IP端口(在本例中是65000)进行监听,我们需要创建一个TCPListener类的实例。 TCPListenertcpListener=newTCPListener(65000); 一旦创建后,就让它开始进行监听。 tcpListener.Start(); 现在就要等待客户连接的要求了。 SocketsocketForClient=tcpListener.Accept(); TCPListener对象的Accept方式返回一个Socket对象,Accept是一个同步的方式,除非接收到一个连接哀求它才会返回。假如连接成功,就可以开始向客户发送文件了。 if(socketForClient.Connected) { ??? 接下来,我们需要创建一个NetworkStream类,将报路传递给constructor: NetworkStreamnetworkStream=newNetworkStream(socketForClient); 然后创建一个StreamWriter对象,只是这次不是在文件上而是在刚才创建的NetworkStream类上创建该对象: System.IO.StreamWriterstreamWriter= newSystem.IO.StreamWriter(networkStream); 当向该流写内容时,流就通过网络被传输给客户端。 客户端的创建 客户端软件就是一个TCPClient类的详细例子,TCPClient类代表连向主机的一个TCP/IP连接。 TCPClientsocketForServer; socketForServer=newTCPClient("localHost",65000); 有了TCPClient对象后,我们就可以创建NetworkStream对象了,然后在其上创建StreamReader类: NetworkStreamnetworkStream=socketForServer.GetStream(); System.IO.StreamReaderstreamReader= newSystem.IO.StreamReader(networkStream); 现在,只要其中有数据就读取该流,并将结果输出到控制台上。 do { outputString=streamReader.ReadLine(); if(outputString!=null) { Console.WriteLine(outputString); } } while(outputString!=null); 为了对这一段代码进行测试,可以创建如下一个测试用的文件: Thisislineone Thisislinetwo Thisislinethree Thisislinefour 这是来自服务器的输出: Output(Server) Clientconnected SendingThisislineone SendingThisislinetwo SendingThisislinethree SendingThisislinefour Disconnectingfromclient... Exiting... 下面是来自客户端的输出: Thisislineone Thisislinetwo Thisislinethree Thisislinefour 返回类别: 教程 上一教程: asp.net生成HTML 下一教程: MS.Net CLR 扩展PE结构分析(转,很不错的文章) 您可以阅读与"使用基本类库 -- zt 统一教学网"相关的教程: · 映射 -- zt 统一教学网 · 微软.NET平台中类型使用的基本原理 · 使用 Visual Basic .NET 重载事件处理程序(zt) · 微软.NET平台中类型使用的基本原理----微软 .NET平台系列文章之二(译文/赵湘宁) · 使用CodeDom开发基于B/S的.NET+MSSQL代码生成器的随感 |
| 快精灵印艺坊 版权所有 |
首页 |
||