【问题标题】:Why should I use asynchronous operation over synchronous operation?为什么我应该使用异步操作而不是同步操作?
【发布时间】:2011-12-14 06:57:33
【问题描述】:

我一直在思考这个问题。

假设我们有一个使用 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();
    }
}

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

【问题讨论】:

  • 因为你喜欢挑战?
  • 您没有提及您使用的平台,但我可以推断它不是 SilverLight。在 SL 中,您无法选择。
  • 有趣的是,如果我没记错的话,异步 webrequest 方法并不是完全异步的,而是阻塞了部分操作,例如 DNS 查找。
  • @Henk 一般而言。我的只是一个例子。恰好与网络请求相关。

标签: c# concept


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

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

        在 C# 5 中,通过await,这与您的第二个示例相比没有更多的工作。

        【讨论】:

        • 期待。有什么时间发布的消息吗?
        • @James 你的意思是 RTM?没有线索。
        【解决方案5】:

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

        Performance difference between Synchronous HTTP Handler and Asynchronous HTTP Handler

        【讨论】:

        • 这里的问题太具体了
        【解决方案6】:

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

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

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

        【讨论】:

        • 3 更多的是流式 va 缓冲的问题,它与异步正交;为了反驳这个例子,你还可以有一个流同步 API(例如 Stream.Read 或 ReadLine),或者一个完全缓冲的异步 API
        猜你喜欢
        • 2014-11-27
        • 2015-07-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-02
        • 2023-03-16
        • 2019-01-20
        相关资源
        最近更新 更多