异步调用在C#中的应用浅析
作者:山东人在成都
当同步调用一项很耗资源的运算时,整个应用程序,看起来就像死掉一样,在运算结束前不会有任何响应.任何一 个程序设计者都不希望发生这样的事,除非是必须.
解决的一个好办法,就是让一个另外的线程去执行那项消耗资源的运算,而不妨碍主线程的正常运行..NET Framework提供了异步调用,它需要定义与需要调用的方法具有相同签名的委托,实质上.NET通过委托将所调用的方 法置于新线程上运行.如果不想有线程调用的烦琐,异步调用是不错的选择.
委托为异步调用提供了BeginInvoke和EndInvoke方法.BeginInvoke方法用于启动异步调用,它包含有与异步执 行的方法相同的参数,并且还有另外两个参数AsyncCallback callback和object asyncState,启动后BeginInvoke会 立即返回,不等待异步调用完成,返回IAsyncResult,用以监视调用进度. EndInvoke方法用于检索异步调用结果,如 果异步调用尚未完成,EndInvoke将一直阻塞至异步调用完成.EndInvoke的参数除了委托调用的异步方法的out或ref 参数外,还有BeginInvoke方法返回的IAsyncResult.
经常使用的异步调用方法有四种,即在调用BeginInvoke后经常有四种方式进行后续处理.
第一种方式最简单,调用BeginInvoke后,直接调用EndInvoke方法,这将一直阻塞到方法运算结束.
第二种方式使用IAsyncResult.AsyncWaitHandle取得WaitHandle,并使用它的WaitOne方法将执行一直阻塞到发 出WaitHandle信号,然后调用EndInvoke.
第三种方式是轮询由BeginInvoke返回的IAsyncResult,确定异步调用完成然后再调用EndInvoke.在轮询过程中 ,可以处理其他事务,或者更新界面部分.
第四种方式是将回调方法的委托传递给BeginInvoke,该方法在异步调用完成后在线程池上执行,该回调方法可 以调用EndInvoke.
第一,二种方式,仍然会使主程序停止响应,看起来就像是同步调用,没有预期的效果,第三种方式则very good, 异步调用后,该做什么事就做什么事,第四种方式没有测试,不知道效果如何.
附加测试代码:
using System; public class TestAsync { delegate string MethodDelegate(); private string TestCallMethod() { Console.WriteLine("async method"); return "hello"; } public void AsyncCall1() { MethodDelegate md = new MethodDelegate(this.TestCallMethod); IAsyncResult ar = md.BeginInvoke(null, null); string s = md.EndInvoke(ar); Console.WriteLine(s); } public void AsyncCall2() { MethodDelegate md = new MethodDelegate(this.TestCallMethod); IAsyncResult ar = md.BeginInvoke(null, null); ar.AsyncWaitHandle.WaitOne(); string s = md.EndInvoke(ar); Console.WriteLine(s); } public void AsyncCall3() { MethodDelegate md = new MethodDelegate(this.TestCallMethod); IAsyncResult ar = md.BeginInvoke(null, null); while (!ar.IsCompleted) { //该做啥事做啥事
} string s = md.EndInvoke(ar); Console.WriteLine(s); } public static void Main() { TestAsync ta = new TestAsync(); ta.AsyncCall(); } } |
阅读(1289) | 评论(1) | 转发(0) |