.net中的异步操作
1.基于委托的异步操作
2.基于IAsyncResult的异步操作
3.基于事件的异步操作
4.基于线程的异步操作
5.基于线程池的异步操作
6.基于backgroundworker的异步操作
/// <summary> /// 使用BackgroundWorker实现异步调用 /// </summary> /// <param name="str"></param> private void UseBackgroundWorker(string str) { BackgroundWorker worker = new BackgroundWorker(); worker.DoWork += new DoWorkEventHandler(worker_DoWork); worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted); worker.RunWorkerAsync(str); } void worker_DoWork(object sender, DoWorkEventArgs e) { Thread.Sleep(5000); MessageBox.Show(e.Argument.ToString());//e.Argument就是传过来的str参数 } void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { //回调函数中就可以访问界面组件了 textBox1.Text = "运行完毕"; }
一些代码:
private void button1_Click(object sender, EventArgs e) { //ThreadPool.QueueUserWorkItem(dosomething,5); //使用线程池的方式调用 //ThreadPool.QueueUserWorkItem(dosomething); //MessageBox.Show("button1"); Func func = new Func(dosomething); string ar = ""; func.BeginInvoke(888, FuncCallBack, ar); //也可以在调用异步方法时不指定回调函数,在适当的时候调用即可。 //IAsyncResult ar = func.BeginInvoke(888,null,null); //func.EndInvoke(ar); //end方法是阻塞的,如果想让界面先弹出ss的提示框,就需要将这句代码放在后面(所以说是适当的时候调用) MessageBox.Show("ss"); } public void FuncCallBack(IAsyncResult ar) { try { Func func = (ar as AsyncResult).AsyncDelegate as Func; func.EndInvoke(ar); } catch (Exception ex) { MessageBox.Show(ex.Message+""+"我检测到了异常"); } } public static void dosomething(object s) { Thread.Sleep(5000); MessageBox.Show("5秒后"); } public static void dosomething(int value) { Thread.Sleep(5000); MessageBox.Show("我运行玩啦"); }
各种异步调用方式的适用范围:
1. 委托异步调用:由于它的实现是将原本需要阻塞的操作交给线程池的工作线程来处理了, 此时线程池的工作线程被阻塞了。因此,此方法对于依赖【线程池的工作线程】来处理任务的编程模型来说是没有意义的。 比如:Asp.net, Windows Services这类服务类的编程模型。但对于WinForm这样的单线程编程模型来说, 是比较方便的,尤其是还可以实现并行执行一些任务。
2. 使用IAsyncResult接口实现异步调用:它的实现是将原本需要阻塞的操作交给线程池的I/O完成线程来处理了, 而在.net中,还没有任何编程模型使用此类线程来执行处理任务,因此,适合于任何编程模型。 但并不是所有的API都支持此类接口,因此适用面有限,且使用较为复杂,尤其是某个过程需要多次异步调用时。 一般说来,许多I/O操作(文件I/O操作以及网络I/O)是支持此类API接口的。
3. 基于事件的异步调用模式:这种方式可以认为是一种封装模式,主要是为了简化线程模型以及简化调用方式,增强了API的易用性。 如果此模式用于对IAsyncResult接口(并非委托异步)实现包装,那么它具有第2种方法的所有优点。
4. 创建新线程的异步方式:这种方式有点特殊,主要和什么样的编程模型以及创建了多少线程有关。 对于服务类的编程模型来说,如果每次的请求处理都采用这种方式,显然会创建大量线程,反而损害性能。 反之,在其它情况下也是可以考虑的。
5. 使用线程池的异步方式:基本上与第1种相似,不适合一些服务类的编程模型,仅仅适用于与用户交互的桌面程序。
6. 使用BackgroundWorker的方式:其实也是在使用线程池的工作线程,因此最适用的领域与1,5相似,只是它在使用上更方便而已。
一般说来,在.net中,标准的异步模式都是使用IAsyncResult接口, 因此后三种方法并不算是真正的异步,但它们却实可以在某些场合下实现异步效果。