这里说的异步编程并不是AJAX等的Web异步编程,而仅仅是DotNet中多线程的异步编程.这种多线程的异步编程主要用来解决某些受计算操作影响而引起主线程阻塞的问题.让程序(主要是窗体应用程序)看跑得更流畅.在dotnet的CLR以及API方法中有简单易用的方法供我们实现异步编程,并且都有相似的调用方法,诸如BeginXXX,EndXXX,IAsyncResult对象,同时也都涉及到回调,委托等操作.下面是一些简单的应用
1.异步IO操作,基本上就是按参数传递
// 值得注意的是最好给定FileOptions.Asynchronous,相对效率会高些 FileStream fs = new FileStream("E:\\test.txt", FileMode.Open, FileAccess.Read, FileShare.Read, 1024, FileOptions.Asynchronous); byte[] data = new byte[(int) fs.Length]; // 开始读取 fs.BeginRead(data, 0, data.Length, delegate(IAsyncResult ar) { // 这里是读取结束之后回调的委托方法内容 fs.EndRead(ar); fs.Close(); string content = Encoding.Default.GetString(data); Console.WriteLine(content); }, fs);
2.读取数据库内容的异步操作,这里的代码是用在窗体程序中,涉及到一个跨线程改变窗体控件的问题,但是在窗体里,只有通过窗体的主线程来改变控件的行为.如下异步读取数据,读取数据的操作是在另外一个线程中,因此试图在这个线程中操作窗体控件是徒劳的,还会出异常.所以只能通过窗体的invoke方法,调用一个委托,这样才能实现.当然这里只是为了提出这个问题,其他的解决的方法还是有的,比如效率更低的轮询方法.
// 这个委托 用于在窗体的主线程中调用 private delegate void FillGridHandler(SqlDataReader reader); private void AsnDataAccess() { // 对于异步操作的数据访问,连接字符串里必须设置Async=True string conStr = ConfigurationManager.ConnectionStrings["NorthWind"].ConnectionString; SqlConnection con = new SqlConnection(conStr); SqlCommand command = new SqlCommand("select [CompanyName] from [Suppliers]", con); con.Open(); command.BeginExecuteReader(delegate(IAsyncResult ar) { SqlDataReader reader = command.EndExecuteReader(ar); // 对于窗体应用程序的 GridView的绑定 FillGridHandler fillGridHandler = delegate(SqlDataReader reader1) { DataTable dt = new DataTable(); dt.Load(reader1); reader.Close(); dataGridView1.DataSource = dt; }; // 用窗体自身的线程去触发委托方法 才能改变窗体里控件属性 this.Invoke(fillGridHandler, reader); }, command, System.Data.CommandBehavior.CloseConnection); }
3.异步触发委托的方法,异步编程离不开委托,其本身也就是调用了委托的异步方法,其内部就必定有一个委托对象
delegate int CalSumHandler(int number); private static void DelegateAsyn() { CalSumHandler handler = delegate(int number) { int sum = 0; for (int i = 0; i < number; i++) { sum += i; } return sum; }; int n = 10; handler.BeginInvoke(n, delegate(IAsyncResult ar) { int res = handler.EndInvoke(ar); Console.WriteLine("result from asyndelegate,sum = {0}", res); }, n); }