13.1.1 异步工作流为什么重要?

13.1.1 异步工作流为什么重要?

假设我们要下载网页的内容,在应用程序中使用,我们可以使用 System.Net 命名空间下的 WebClient 类,但下不能演示我们需要解决的问题,运行复杂、长时间的操作。相反,我们将首先显式创建 HTTP 请求,然后,下载数据:

var req =HttpWebRequest.Create("");

var resp = req.GetResponse(); <– 初始化连接

var stream = resp.GetResponseStream();

var reader = new StreamReader(stream); <– 下载网页

var html = reader.ReadToEnd();

Console.WriteLine(html);

这段代码虽然能运行,但远不完美,它在两个地方执行 HTTP 通讯。第一,它需要初始化与服务器的 HTTP 连接;第二,下载网页。两个操作都可能会花很长时间,每一个都可能会阻塞活动的线程,从而导致我们的应用程序没有响应。

要解决这个问题,我们可以在单独的线程中进行下载,但是,使用线程代价昂贵,所以,这种方法会限制我们能够并行运行的下载的数量;此外,大部分时间线程是等待响应,因此,没有理由浪费线程资源。要完美地解决问题,我们应使用异步编程接口,它能够触发请求,,在操作完成时,执行提供的回调:

var req = HttpWebRequest.Create("");

req.BeginGetResponse(asyncRes1 => { <– 启动操作

var resp =req.EndGetResponse(asyncRes1);

var stream =resp.GetResponseStream();

var reader = newStreamReader(stream);

reader.BeginReadToEnd(asyncRes2=> { <– 不退出

var html =reader.EndReadToEnd(asyncRes2);

Console.WriteLine(html);

});

});

要写这种代码,是很难的。虽然我们使用了 C# 3.0 的 lambda 函数,代码看起来仍然很复杂。我们必须改变其结构;不能顺序地写代码,而是用嵌套的回调的序列。

前面的代码段还有另外一个问题,在 .NET 框架中并没有BeginReadToEnd 方法,因此,我们可能必须自己实现异步下载。不幸的是,不可能使用简单的顺序代码实现,因为我们需要以缓冲的方式下载页面。如果以异步风格写这段代码(使用嵌套的回调),我们不可能使用任何内置的结构,例如,while 循环。

我们将会看到,异步工作流能解决所有在写下载程序时遇到的问题,能够以通常的顺序方式写代码,使用标准的控制结构,比如递归,或者甚至是 while 循环。代码异步执行,因此,工作流等待操作完成,而不需要使用专门的线程。在下一节,我们将学习如何使用 F# 异步工作流,来实现我们刚讨论的示例。

突然之间失去了语言。那才是真正的寂寞,

13.1.1 异步工作流为什么重要?

相关文章:

你感兴趣的文章:

标签云: