为什么我应该使用异步操作而不是同步操作?

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();
    }
}

那么为什么我要使用更加复杂的异步操作,而不是更简单的同步操作呢?是为了节约系统资源吗?


2
因为你喜欢挑战吗? - H H
1
你没有提到你使用哪个平台,但我可以推断出它不是SilverLight。在SL中,你没有选择的余地。 - H H
1
有趣的是,如果我没记错的话,异步Web请求方法并不完全是异步的,而是会阻塞某些操作的,比如DNS查找。 - CodesInChaos
@Henk 一般而言。我的只是一个例子。恰好与网络请求有关。 - deutschZuid
6个回答

9
如果您进行异步请求,您可以在等待响应时做其他事情。如果您进行同步请求,则必须等待接收到响应后才能做其他事情。
对于简单的程序和脚本,可能并不太重要,事实上,在许多情况下,更容易编码和理解的同步方法将是更好的设计选择。
然而,对于非平凡的程序,例如桌面应用程序,同步请求会锁定整个应用程序,直到请求完成,这会导致不可接受的用户体验。

6

同步操作会阻止您在等待请求完成或超时时做其他事情。使用异步操作可以让您为用户显示程序正在忙碌的状态,甚至让他们继续使用其他功能区域。


6

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

同步进行网络操作意味着您的应用程序和 UI 将在整个操作期间阻塞。不少见的网络故障可能会导致您的应用程序阻塞数分钟,而无法取消。这会导致非常不满意的客户。


4
异步技术在你的工作量大于你的核心数量时特别有用 - 例如,你可能有很多活跃的Web请求、一些文件访问操作、几个DB调用,以及其他一些网络操作(WCF或redis)。如果所有这些都是同步的,那么你会创建大量的线程、大量的堆栈,并遭受大量的上下文切换。如果你可以使用异步API,你通常可以利用池线程在每个操作“执行”某些事情的短暂时刻中完成操作。这对于高吞吐量的服务器环境非常有用。拥有多个核心是好的,但更有效率才是更好的选择。
在C# 5中,通过await,这变得和第二个示例一样简单。

期待着它的发布。有没有关于它何时发布的消息? - deutschZuid
@James 你是指RTM吗?我不知道。 - Marc Gravell

2

1
那个问题太具体了。 - zerkms

1

1) 如果你被限制在像Silverlight这样的单线程环境中,那么你别无选择,只能使用异步调用,否则整个用户线程将会锁死。

2) 如果你有许多需要长时间处理的调用,为什么要阻塞整个线程呢?可以让线程在等待返回时继续做其他事情。例如,如果我有五个每个需要5秒钟的函数调用,我希望立即启动它们,并根据需要返回。

3) 输出数据量太大,同步处理输出数据会导致缓冲区溢出并锁定程序。如果我有一个程序将10GB的数据写入控制台,并且我想读取输出,我可以异步逐行处理。如果我同步处理,那么我将会耗尽缓冲区空间并锁定程序。


3更多是流式传输与缓冲的问题,这与异步无关。要反驳这个例子,您也可以有一个流同步API(例如Stream.Read或ReadLine),或者一个完全缓冲的异步API。 - Marc Gravell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接