版权声明:转载请注明出处。 https://blog.csdn.net/baidu_38304645/article/details/84678110
这篇文章我们学习如何用异步编程来读取文件。
使用System.IO.Stream类的异步调用方法,对文件out.txt进行异步读操作。
运行结果:
源代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Runtime.Remoting.Contexts;
using System.IO;
namespace Test1_1
{
class HelloWorld
{
static void Main(string[] args)
{
//实例化异步I/O测试器
AsynchIOTester theApp = new AsynchIOTester("D:\\out.txt");
//创建回调委托对象
AsyncCallback myCallBack = new AsyncCallback(OnReadDone);
//开始异步读操作
IAsyncResult ar = theApp.InputStream.BeginRead(
theApp.Buffer, //存放结果的缓存
0, //偏移值
theApp.Buffer.Length, //缓冲大小
myCallBack, //回调方法
theApp); //局部状态对象
Console.WriteLine("++++++主线程继续工作+++++");
Thread.Sleep(1000);
Console.WriteLine("\n\n++++++++主线程工作完成,执行了1秒,等待异步调用完成\n");
Console.Read();
}
//回调方法
static void OnReadDone(IAsyncResult ar)
{
//获取局部状态对象
AsynchIOTester test = (AsynchIOTester)ar.AsyncState;
//结束异步读操作,返回读取的字节数
int bufferCount = test.InputStream.EndRead(ar);
if (bufferCount > 0)
{
//模拟下一次读取间隔0.1s,以免较快读完
Thread.Sleep(100);
//转换成指对编码的字符串
string s = Encoding.GetEncoding("GB2312").GetString(test.Buffer, 0, bufferCount);
Console.Write(s);
//创建回调委托对象
AsyncCallback myCallBack = new AsyncCallback(OnReadDone);
//如果没有读完,再次异步调用BeginRead
test.InputStream.BeginRead(test.Buffer, 0, test.Buffer.Length, myCallBack, test);
}
}
}
//异步I/O测试器
public class AsynchIOTester
{
private Stream inputStream; //输入流
private byte[] buffer; //存入读入数据的缓冲区
private string filename;
public AsynchIOTester(string filename) //构造函数
{
this.filename = filename;
inputStream = File.OpenRead(filename); //打开文件
buffer = new byte[16]; //分配缓冲
}
public byte[] Buffer
{
get { return buffer; }
}
public Stream InputStream
{
get { return inputStream ;}
}
}
}
主线程首先创建了一个AsynchIOTester异步I/O测试器对象(即theApp)。该对象包括输入流,缓冲区等信息。程序可以在回调时获取它。然后,主线程中声明了一个AsyncCallBack类型的委托对象myCallback,用于创建回调委托对象。该对象绑定了回调方法OnReadDone()。接下来,调用BeginRead()方法,进行文件的异步读取,之后我们使用Thread.Sleep(1000)来模拟需要执行的操作耗时1秒。这时,异步调用已经开始,因为不希望一次异步调用就读完整个文件,因此,将缓冲区设为16个字节。
当读取完成时,CLR将调用回调方法OnReadDone()。在OnReadDone()方法中,我们首先用(AsynchIOTester)ar.AsyncState获取调用开始时封装的异步I/O数。如果字节数大于0,将缓冲转换成字符串并输出,然后再次调用BeginRead,开始下一次异步读取,为避免因为较快读完,而无法验证是否进行了异步调用,我们使用Thread.Sleep(100),使之在0.1秒后再进行下一个操作。