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

本文关键字:同步操作 异步操作 我应该 为什么 | 更新日期: 2023-09-27 18:17:41

我一直在思考这个问题。

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

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

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

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

如果您进行异步请求您可以在等待请求响应时做其他事情。如果你做了一个同步的请求,你必须等待直到你收到你的响应,直到你可以做别的事情。

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

然而,对于重要的程序,比如桌面应用程序,一个同步请求会锁定整个应用程序,直到请求完成会导致不可接受的用户体验

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

同步版本更容易编写代码,但它掩盖了一个非常严重的问题。网络通信,或者实际上是I/O操作,可能会阻塞并持续很长一段时间。例如,许多网络连接都有2分钟的超时。

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

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

在c# 5中,通过await,这变得不比第二个例子多。

前几天我读到这篇文章,以前也有人思考过类似的问题:

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

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

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

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