在本章中,我们将探讨一下如何在不使用C# 5.0以及async的情况下去编写异步代码。这样做会帮助你理解异步背后到底发生了什么。基于这个原因,我会带着你快速过一下例子,然后将需要我们重点理解的地方告诉你。
.NET中采用的异步模式
正如我之前所说,Silverlight只提供异步版本的API。下面是一个下载网页内容并进行显示的例子
private void DumpWebPage(Uri uri)
{
WebClient webClient = new WebClient();
webClient.DownloadStringCompleted += OnDownloadStringCompleted;
webClient.DownloadStringAsync(uri}
}
private void OnDownloadStringCompleted(object sender, DownloadStringCompletedEventArgs eventArgs)
{
m_TextBlock.Text = eventArgs.Result;
}
像这种类型的API被称作基于事件的异步模式(Event-based Asynchronous Pattern - EAP)。其基本思想:没用采用同步方法来下载网页,因为这样会导致下载完成前程序被阻塞,EAP采用的是一个方法外加一个事件的方式。下载网页的方法看起来和同步方法很相似,只不过它的返回值是void,事件的处理方法的参数带着下载下来的网页信息。
程序在调用下载网页的API(第5行)之前先订阅了DownloadStringCompleted事件,因此当执行到第5行时方法会立即返回——因为这是异步的API。这样,当将来下载的工作完成后,API内会触发DownloadStringCompleted事件,从而之前订阅的事件回调方法(OnDownloadStringCompleted)就被执行了。
这种模式看起来有点乱,因为它需要将原本应该很简单的流程分割成了两个方法。更重要的是,你还需要订阅事件,而这无形之中又增加了复杂性。如果你在程序中继续使用webClient实例去处理其它请求,你应该不希望它原来订阅的事件在新的请求中被触发。
另外一种异步模式用到了IAsyncResult接口。举个例子:Dns类中有一个方法BeginGetHostAddresses可以根据主机名查询其IP地址,这种模式需要两个方法,一个叫做BeginMethodName,它的职责是开始耗时操作;另一个方法被命名为EndMethodNameÿ