5

我一直在思考这个问题。

假设我们有一个使用 HttpWebRequest 类的简单异步 Web 请求

class webtest1
{
    HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("www.google.com");

    public webtest1()
    {
        this.StartWebRequest();
    }

    void StartWebRequest()
    {
        webRequest.BeginGetResponse(new AsyncCallback(FinishWebRequest), null);
    }

    void FinishWebRequest(IAsyncResult result)
    {
        webRequest.EndGetResponse(result);
    }
}

通过同步操作可以轻松实现相同的目的:

class webtest1
{
    HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("www.google.com");

    public webtest1()
    {
        webRequest.GetResponse();
    }
}

那么,当一个更简单的同步操作就足够时,我为什么要使用更复杂的异步操作呢?节省系统资源?

4

6 回答 6

9

如果您发出异步请求,您可以在等待对请求的响应时做其他事情。如果您发出同步请求,则必须等到收到响应后才能执行其他操作。

对于简单的程序和脚本,这可能并不重要,实际上在许多情况下,更容易编码和理解同步方法将是更好的设计选择。

但是,对于非平凡的程序,例如桌面应用程序,锁定整个应用程序直到请求完成的同步请求会导致不可接受的用户体验

于 2011-12-13T22:57:33.943 回答
6

同步操作将阻止您在等待请求完成或超时时执行任何其他操作。使用异步操作可以让您为用户制作动画以显示程序正忙,甚至让他们继续使用其他功能区域。

于 2011-12-13T22:51:20.803 回答
6

同步版本的代码更简单,但它掩盖了一个非常严重的问题。网络通信,或真正的 I/O 操作,可能会阻塞并持续很长时间。例如,许多网络连接的超时时间为 2 分钟。

同步执行网络操作意味着您的应用程序和 UI 将在该操作的整个持续时间内阻塞。一个常见的网络故障可能会导致您的应用程序阻塞几分钟而无法取消。这会导致客户非常不满意。

于 2011-12-13T22:52:56.073 回答
4

当您处理的事情多于核心时,异步变得特别有用 - 例如,您可能有许多活动的 Web 请求、许多文件访问操作、很少的 DB 调用,可能还有一些其他网络操作(WCF 或redis 也许)。如果所有这些都是同步的,那么您将创建大量线程、大量堆栈并遭受大量上下文切换。如果您可以使用异步 API,您通常可以在每个操作执行某项操作的短暂时刻利用池线程。这对于高吞吐量服务器环境非常有用。拥有多个核心固然很棒,但效率更高。

在 C# 5 中,这变成了 via await,不比你的第二个例子更多的工作。

于 2011-12-13T22:55:36.923 回答
2

前几天我正在阅读这篇文章,之前曾思考过一个类似的问题:

同步 HTTP 处理程序和异步 HTTP 处理程序之间的性能差异

于 2011-12-13T22:52:21.380 回答
1

1)你被困在一个单线程的环境中,比如silverlight。在这里你别无选择,只能使用异步调用,否则整个用户线程将被锁定。

2) 你有很多电话需要很长时间才能处理。 当它可以在等待返回的同时继续做其他事情时,为什么要阻塞你的整个线程呢?例如,如果我有五个函数调用,每个调用需要 5 秒,我想立即启动所有函数并让它们在必要时返回。

3)输出中同步处理的数据过多。如果我有一个向控制台写入 10 GB 数据的程序并且我想读取输出,我就有机会异步地逐行处理。如果我同步执行此操作,那么我将用完缓冲区空间并锁定程序。

于 2011-12-13T22:52:11.100 回答