与.NET异步处理相比,在SQL Server中使用异步处理有什么优势?它们不是一样的吗?我很难理解在SQL Server中使用异步处理而不是在.NET中使用异步处理有什么好处。我可以很容易地将SQL调用包装在一个lambda表达式中并执行BeginInvoke(...)。
有人能告诉我两者的区别和好处吗?
发布于 2009-11-14 12:08:10
.NET异步处理(BeginInvoke(...))的问题在于,它所做的一切都是从一个线程中分离出来,以便同步处理代码。一个5分钟的查询将占用一个线程5分钟,在远程端计算结果时阻塞(即大约99%的时间什么都不做)。在压力下(同时有多个查询),这将耗尽线程池,使所有线程都处于阻塞状态。线程池将变得无响应,新的工作请求将遭受巨大的延迟,等待线程池启动额外的线程。这不是线程池的预期用途,因为它的设计期望它被要求完成的任务是短暂的和非阻塞的。
使用Begin/EndAction APM对,可以以非阻塞方式调用相同的操作,并且只有当结果通过IO完成端口返回时,它才会在线程池中作为工作项排队。在此期间,您的线程都不会被占用,在处理排队响应时,数据是可用的,这意味着用户代码不会阻塞IO,并且可以快速完成……更有效地使用线程池,它可以扩展到更多的客户端请求,而不需要为每个未完成的操作花费一个线程。
发布于 2009-11-17 00:18:14
正如在前面的答案中所提到的,BeginInvoke使用.NET线程。但同样重要的是,线程来自ASP.NET线程池,因此它会与客户端竞争非常有限的线程资源。ThreadPool.QueueUserWorkItem()也是如此。
SqlClient异步呼叫需要启用了async=true的SqlConnection。该模式需要稍微多一点的网络开销(这就是默认情况下不启用它的原因),但它不会消耗.NET线程池中的线程。相反,它使用异步I/O。
后一种方法的优点是它的可伸缩性更强。您可以通过这种方式处理成百上千个并发请求,其中每个线程调用的开销将是极端的。此外,您将很快使用整个ASP.NET线程池(默认情况下,它最多只有大约12个线程)。
发布于 2009-11-14 13:31:55
.Net BeginInvoke只是将执行推迟到不同的线程中。这将始终比同步调用慢,并消耗额外的资源。使用此方法的唯一原因是释放调用者上下文以继续执行其他操作(例如,向客户端返回HTTP请求的结果)。
当连接的AsynchronousProcessing属性设置为true并使用SqlCommand的BeginExecute方法时,SqlCommand异步方法才是真正的异步方法。SQL命令被发送到网络通信通道,并在服务器返回结果时调用完成。
但是,从可靠性的角度来看,这两种方法都没有用。它们都依赖客户端进程保留,直到调用完成,否则SQL Server将看到客户端断开连接并放弃处理,回滚任何中间工作。考虑一个ASP应用程序,它接受了一个HTTP请求,提交了一个“异步”支付处理并返回了一个响应。没有任何方法可以保证提交的工作确实会发生。
对于需要可靠性保证的处理情况,解决方案是将服务器上的工作排入队列,提交它,然后依靠SQL server自己的异步处理功能继续进行。这是一种即使在客户端断开连接、ASP进程“回收”、SQL Server镜像或集群故障转移、硬件灾难恢复等情况下也能保证处理的方法,因为它是提交异步处理请求的一种事务性持久方式。有关示例,请参阅Asynchronous Procedure Execution。
https://stackoverflow.com/questions/1733027
复制相似问题