在处理客户端请求时,为什么异步模式比同步模式更好?

时间:2010-07-01 21:44:15

标签: c# asynchronous client-server

我有一个客户端 - 服务器项目,正在寻找更好的方法来处理来自客户端的请求。有人建议异步模式比同步模式和线程池模式更好 我的问题是为什么?异步模式有缺点吗?

6 个答案:

答案 0 :(得分:7)

是的,通常可以在不花费线程的情况下处理异步请求。操作系统对它们有特殊支持,例如重叠I / O和完成端口等功能。他们基本上做的是利用内核线程的费用,无论如何都需要,因为驱动程序需要能够处理来自多个用户模式程序的多个请求。 .NET框架在其BeginXxx()方法中很容易利用它。

使用线程池线程也很便宜,但是你受到线程池调度程序的行为的影响。这与创建更多TP线程并不像核心那么多。 TP线程永远不应该用于可以暂时阻塞的代码,这对于CS任务来说非常典型,例如建立连接。

异步代码中的错误处理非常困难。当EndXxxx()方法引发异常时,通常只有很少的上下文。它发生在一个回调线程上,离主逻辑很远。好的,当你可以耸耸肩“没有发生,让我们记录下来”,当程序的状态依赖于它时,总是会发生错误。在后一种情况下始终选择同步模式。

答案 1 :(得分:2)

您不想阻止用户界面。通过异步操作,您可以在等待服务器响应时执行其他操作。

答案 2 :(得分:2)

异步模式可让您继续处理同步模式让您等待。

答案 3 :(得分:1)

同步操作的一个缺点是IMO你不能打断它们 - 例如当您的服务器应用程序调用同步方法WaitForConnection()并且没有客户端连接时,您无法停止等待...

例如,尝试查看此What is a good way to shutdown Threads blocked on NamedPipeServer#WaitForConnection?

答案 4 :(得分:1)

用Hans的答案“标记”:I / O操作与线程的独立性允许更加显着的缩放;成千上万的未完成请求是可能的,而使用线程无法完成。

此外,当您启动considering the complexities of error handling in protocol design时,事实证明异步方法的复杂性远远低于正确编写同步代码的复杂性。大多数同步套接字代码看起来更简单,但实际上包含微妙的错误。

如果双方发送的数据多于读取数据,异步方法对于防止死锁情况也很重要;有关更多讨论,请参阅this blog post

如果您希望在线程安全包装器中具有可靠性优势和(大多数)异步I / O的性能优势(具有更简单的错误处理),请考虑Nito.Async库。

答案 5 :(得分:0)

在同步服务器中,您需要在访问数据结构时处理锁​​定(如果存在更新),这需要时间和代码(并且是难以发现的错误的来源)。还有许多(例如数千个)线程在许多实现中引起技术问题(例如,用于堆栈分配),并且如果服务器是IO绑定的,那些线程几乎都在休眠(等待网络)并且只是浪费内存。

在单个线程上使用异步模型可以忽略锁定问题(这意味着您的处理速度尽可能快)并且您只使用客户端实际需要的内存(只有一个堆栈)。 / p>

但是现在多核计算机很常见,因此部分优势会丢失(因为如果修改共享数据结构就要锁定)。在N个异步服务器前面使用平衡器可能会获得最佳效率,其中N是您环境的最佳线程数。

异步方法的坏处在于,根据您的工具,代码可能非常丑陋且难以理解,并且如果计算不是微不足道的,并且错误地处理进入无限循环,则整个异步服务器将无响应(所以可能应该增加一个看门狗。)