对于访问异步操作的结果,应用程序开发人员有若干种设计选择。正确的选择取决于应用程序是否有可以在操作完成时执行的指令。如果应用程序在接收到异步操作结果之前不能进行任何其他工作,则必须先阻止该应用程序进行其他工作,等到获得这些操作结果后再继续进行。若要在异步操作完成之前阻止应用程序,您可以使用下列方法之一:
-
从应用程序的主线程调用 EndOperationName,阻止应用程序执行,直到操作完成之后再继续执行
使用 Dns 类中的异步方法来检索用户指定的计算机的域名系统信息。
IAsyncResult result = Dns.BeginGetHostEntry("127.0.0.1",null,null); Console.WriteLine("Processing your request for information..."); try { IPHostEntry host = Dns.EndGetHostEntry(result); string[] aliases = host.Aliases; IPAddress[] address = host.AddressList; if (aliases.Length>0) { Console.WriteLine("Aliases"); for (int i = 0; i < aliases.Length; i++) { Console.WriteLine(" {0} ",aliases[i]); } } if (address.Length>0) { Console.WriteLine("Addresses"); for (int i = 0; i < address.Length; i++) { Console.WriteLine(" {0} ",address[i].ToString()); } } } catch (SocketException ex) { Console.WriteLine("An exception occurred while processing the request: {0}",ex.Message); }
-
使用 AsyncWaitHandle 来阻止应用程序执行,直到一个或多个操作完成之后再继续执行。
那些在异步操作完成前一直使用一个或多个 WaitHandle 对象阻止其他操作的应用程序通常会调用 BeginOperationName 方法,执行不需要等待操作结果的工作,然后一直等到异步操作完成才停止阻止。通过使用 AsyncWaitHandle 调用 WaitOne 方法之一,应用程序可以阻止一个操作。若要在等待一组异步操作完成期间阻止执行,应将相关的 AsyncWaitHandle 对象存储在数组中,然后调用 WaitAll 方法之一。若要在等待一组异步操作中的任一操作完成时阻止其他操作,应将关联的 AsyncWaitHandle 对象存储在数组中,然后调用 WaitAny 方法之一。
IAsyncResult result = Dns.BeginGetHostEntry("127.0.0.1",null,null); Console.WriteLine("Processing request for information..."); result.AsyncWaitHandle.WaitOne(); //使用与异步操作关联的 WaitHandle 来阻止 try { IPHostEntry host = Dns.EndGetHostEntry(result); string[] aliases = host.Aliases; IPAddress[] address = host.AddressList; if (aliases.Length>0) { Console.WriteLine("Aliases"); for (int i = 0; i < aliases.Length; i++) { Console.WriteLine(" {0} ",aliases[i]); } } if (address.Length>0) { Console.WriteLine("Addresses"); for (int i = 0; i < address.Length; i++) { Console.WriteLine(" {0} ",address[i].ToString()); } } } catch (SocketException ex) { Console.WriteLine("Exception occurred while processing the request: {0}",ex.Message); }
在异步操作完成时不需要阻止的应用程序可使用下列方法之一:
-
按以下方式轮询操作完成状态:定期检查 IsCompleted 属性,操作完成后调用 EndOperationName。
private void button3_Click(object sender, EventArgs e) { IAsyncResult result = Dns.BeginGetHostEntry("127.0.0.1", null, null); Console.WriteLine("Processing request for information..."); while (result.IsCompleted != true) //开始异步操作,直到操作完成 { UpdateUserInterface(); } try { IPHostEntry host = Dns.EndGetHostEntry(result); string[] aliases = host.Aliases; IPAddress[] address = host.AddressList; if (aliases.Length > 0) { Console.WriteLine("Aliases"); for (int i = 0; i < aliases.Length; i++) { Console.WriteLine(" {0} ", aliases[i]); } } if (address.Length > 0) { Console.WriteLine("Addresses"); for (int i = 0; i < address.Length; i++) { Console.WriteLine(" {0} ", address[i].ToString()); } } } catch (SocketException ex) { Console.WriteLine("Exception occurred while processing the request: {0}", ex.Message); } } static void UpdateUserInterface() { Console.WriteLine("更新时间:"+DateTime.Now.ToString()); }
-
使用 AsyncCallback 委托来指定操作完成时要调用的方法。
static int requestCounter; static ArrayList hostData = new ArrayList(); static StringCollection hostNames = new StringCollection(); static void UpdateUserInterfaceTwo() { Console.WriteLine("{0} requests remaining.更新时间:{1}",requestCounter,DateTime.Now.ToString()); } static void ProcessDnsInformation(IAsyncResult result) { string hostName = (string)result.AsyncState; hostNames.Add(hostName); try { IPHostEntry host = Dns.EndGetHostEntry(result); hostData.Add(host); } catch (SocketException ex) { hostData.Add(ex.Message); } finally { Interlocked.Decrement(ref requestCounter); } } private void button4_Click(object sender, EventArgs e) { AsyncCallback callback = new AsyncCallback(ProcessDnsInformation); //创建了引用 ProcessDnsInformation 方法的 AsyncCallback 委托 string host = "127.0.0.1"; Interlocked.Increment(ref requestCounter); Dns.BeginGetHostEntry(host,callback,host); while (requestCounter>0) { UpdateUserInterfaceTwo(); } for (int i = 0; i < hostNames.Count; i++) { object data = hostData[i]; string message = data as string; if (message!=null) { Console.WriteLine("Request for {0} returned message: {1}",hostNames[i],message); continue; } IPHostEntry h = (IPHostEntry)data; string[] aliases = h.Aliases; IPAddress[] address = h.AddressList; if (aliases.Length>0) { Console.WriteLine("Aliases for {0}",hostNames[i]); for (int j = 0; j < aliases.Length; j++) { Console.WriteLine(" {0} ",aliases[j]); } } if (address.Length>0) { Console.WriteLine("Addresses for {0}",hostNames[i]); for (int k = 0; k < address.Length; k++) { Console.WriteLine(" {0} ",address[k].ToString()); } } } }
总结:以上查询IAsyncResult的方法都会阻塞当前进程,尤其是CS程序会出现无响应状态,如果需求是需要阻塞当前线程的可以用上面的方法,正在学习,期待有不阻塞的方法!