【问题标题】:What is the difference between making an Async web service call and making a Synchronous web service call in another thread?在另一个线程中进行异步 Web 服务调用和同步 Web 服务调用有什么区别?
【发布时间】:2013-05-13 21:24:01
【问题描述】:

和/或,何时使用其中之一? 是偏好问题还是技术差异?

关于我为什么要问的一些背景知识: 我有一个运行 .NET 2.0 CF 应用程序的应用程序,并且用户正在执行几个快速操作。我不想阻止操作,但我希望 UI 显示等待图标或进度图标栏。

长时间运行的操作主要是由于 Web 服务调用,然后在设备本身上对返回的数据进行了一些处理。

编辑在查看了 Jim 的回答,特别是下面的引用之后,在避免对 UI 线程施加任何负载的同时执行异步调用的最佳做法是什么?总是在单独的线程中调用 BeginGetResponse?

BeginGetResponse 方法需要一些同步设置任务以 完成(DNS 解析、代理检测和 TCP 套接字连接, 例如)在此方法变为异步之前。因此, 永远不应在用户界面 (UI) 线程上调用此方法 因为这可能需要相当长的时间(最多几分钟 取决于网络设置)完成初始同步 在抛出错误异常或方法之前设置任务 成功。

【问题讨论】:

    标签: c# .net multithreading web-services asynchronous


    【解决方案1】:

    在后台进行同步调用会在调用期间占用一个线程。

    线程不是免费的。尤其是如果您进行大量调用,则会产生大量开销。

    异步调用不涉及单独的线程,因此效率更高。

    【讨论】:

    • 在某种程度上,这取决于内部调用是如何实现的。如果调用只是在内部分派到单个线程,除了浪费一些内存之外,它不会有太大的不同。但是,如果同步调用实际上在调用线程上做了真正的工作,那么如果所有其他内核都忙,那么为十个这样的请求中的每一个做一点点工作可能需要十次上下文切换,这会降低性能。
    • @thefabledone:你在邮箱里放了五个信封。五个邮递员会来接他们吗?
    • @TheFabledOne:这取决于它的实现方式。理想情况下,答案是否定的。
    • @TheFabledOne:你说得对,这类事情可能很棘手。这里的关键概念是确定高延迟任务是否由于受本地处理器速度限制受外部资源限制(如网络服务器。理想情况是 一个线程 处理所有 I/O 受限任务,然后每个处理器一个线程 处理所有处理器受限任务.
    • @TheFabledOne:是“排队”工作还是尝试并行执行的问题是一个很好的问题。如果您以串行方式执行受处理器限制的计算,而不是在两个任务之间切换一个处理器,那么您始终可以获得更高的吞吐量,因此如果您需要的只是结果,那么请始终使用串行方式。但有些任务具有部分结果有用的特性,在这种情况下,有时最好来回切换。基本上你必须平衡 吞吐量响应能力
    【解决方案2】:

    如果您进行异步 Web 服务调用,UI可能会在 DNS 解析期间被占用一小段时间。 BeginGetResponse 方法解析 DNS它进行异步方法调用以获取响应。因此,如果 DNS 解析需要任何时间(通常非常快,但有时可能需要几秒钟),那么 UI 将在这段时间内无响应。

    更多详情请见Is This Really Asynchronous?

    除此之外,只要您在回调中处理响应(在单独的线程上执行),UI 响应性就没有区别。这里的区别在于,对于异步请求,单独的线程仅在处理结果期间处于活动状态。线程执行同步请求时,线程在请求​​和处理的整个持续时间内都处于活动状态。对于大多数 Web 服务调用,处理所需的时间比发出请求并等待结果要少得多。

    如果您发出 很多 个请求,那么每次调用只有一个线程会冒资源耗尽的风险。但在现代硬件上,您必须每秒发出几十个请求才能成为问题。

    说了这么多,您可能应该使用异步 Web 请求。如果您使用这些请求访问同一个域(或少数域),则 DNS 解析将从本地缓存中得到满足,这意味着它根本不需要任何时间。并且您减少(几乎完全消除)由于并发线程过多而导致资源耗尽的风险。

    有趣的是,HttpWebRequest.BeginGetResponse 的文档说:

    BeginGetResponse 方法需要在此方法变为异步之前完成一些同步设置任务(例如 DNS 解析、代理检测和 TCP 套接字连接)。因此,永远不应在用户界面 (UI) 线程上调用此方法,因为在完成初始同步设置任务之前可能需要相当长的时间(取决于网络设置可能需要几分钟)抛出错误异常或方法成功。

    虽然这可能是一个很好的一般建议,但我上面的评论仍然适用:如果您的所有呼叫都转到同一服务器或同一组服务器(通常是内部应用程序的情况),那么该警告是无关紧要的. DNS 将被缓存,代理将被设置等。如果代理设置在每个连接的基础上花费大量时间,您需要与您的 IT 部门联系以获得解决方案。根据我的经验,异步 Web 请求是可行的方法。

    【讨论】:

    • 谢谢!因此,当异步调用正在进行时,没有活动线程在等待它。但是,一旦异步调用完成,新线程是如何产生的(以及是什么触发了新线程激活?)。
    • 没有活动线程在等待它。在底层,它使用 IO 完成端口 (msdn.microsoft.com/en-us/library/windows/desktop/…)。我不知道它们如何工作的细节,但一般来说,它会设置一个事件,在响应返回时由操作系统触发,并触发线程激活。
    • 太好了,谢谢。如果您有任何反馈,我已经用一个额外的问题更新了我的原始帖子,但我认为我足以继续完成当前的任务。
    • @TheFabledOne:见我的附加评论。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 2011-09-03
    • 1970-01-01
    相关资源
    最近更新 更多