在SQL Server中使用异步处理而不是.NET异步处理有什么优势?他们不一样吗?我很难理解在SQL Server中使用异步处理而不是.NET APM的好处是什么。我可以轻松地将一个SQL调用包装在一个lambda表达式中并执行一个BeginInvoke(...)。
有人可以帮助我解决两者的不同和好处吗?
答案 0 :(得分:9)
.NET异步处理(BeginInvoke(...)
)的问题在于,所有这一切都是分离线程以同步处理代码。 5分钟的查询将占用一个线程5分钟,阻塞(即在99%的时间内不做任何事情),同时在远程端计算结果。在压力下(一次多次查询),这将耗尽线程池,将所有线程捆绑在阻塞状态。线程池将变得无响应,并且新的工作请求将遭受等待线程池启动额外线程的大延迟。这不是线程池的预期用途,因为它的设计期望它要求完成的任务是短暂的和非阻塞的。
使用Begin / EndAction APM对,可以以非阻塞方式调用相同的操作,并且只有当结果通过IO完成端口返回时才会将其排队为线程池中的工作项。在过渡期间,你的所有线程都没有被束缚,并且在处理排队响应时,数据可用意味着用户代码不会阻塞IO,并且可以快速完成...更有效地使用threadpool,它可以扩展到更多客户端请求,而不需要每次未完成操作的线程成本。
答案 1 :(得分:5)
如前面的答案所述,BeginInvoke
使用.NET线程。同样重要的是,该线程来自ASP.NET线程池,因此它与客户竞争非常有限的线程资源。 ThreadPool.QueueUserWorkItem()
也是如此。
SqlClient
异步调用需要启用了async = true的SqlConnection
。该模式需要更多的网络开销(这是默认情况下未启用的原因),但它不会消耗.NET线程池中的线程。相反,它使用异步I / O.
后一种方法的优点是它的可扩展性更高。您可以通过这种方式处理数百或数千个并发请求,其中每次调用线程的开销将是极端的。另外,您将非常快速地使用整个ASP.NET线程池(默认情况下它最多只有12个线程)。
答案 2 :(得分:3)
.Net BeginInvoke只是将执行推迟到另一个线程。这将始终比同步调用慢,并消耗额外的资源。使用它的唯一原因是释放调用者上下文以继续进行其他操作(例如,将HTTP请求的结果返回给客户端)。
当连接上的AsynchronousProcessing属性设置为true并且使用SqlCommand的BeginExecute方法时,SqlClient异步方法是真正异步的。 SQL命令将发布到网络通信通道,并在服务器返回结果时调用完成。
从可靠性的角度来看,虽然这两种方法都没有用。他们都依赖客户端进程来保持呼叫,直到呼叫完成,否则SQL Server将看到客户端断开连接并放弃处理,回滚任何中间工作。考虑接受HTTP请求的ASP应用程序,提交“异步”支付处理并返回响应。没有任何方法可以保证提交的作品真正发生。
对于处理需要可靠性的情况,保证解决方案在服务器上排队工作,提交然后继续,依赖SQL Server自己的异步处理功能。这是一种方法,即使存在客户端断开连接,ASP进程“回收”,SQL Server镜像或群集故障转移,硬件灾难恢复,几乎任何可以抛出的东西,都可以保证处理,因为这是一种事务性持久的提交方式异步处理请求。有关示例,请参阅Asynchronous Procedure Execution。
答案 3 :(得分:0)
从这篇文章SQL Server 2008 Books Online (October 2009) - Performing Asynchronous Operations,我引用:
异步处理启用 没有的方法立即返回 阻塞调用线程。这个 允许大部分的力量和 多线程的灵活性,没有 要求开发人员明确 创建线程或句柄 同步。
如果您已经明确创建了这些线程并处理了同步,那么您可能找不到太多差异。
答案 4 :(得分:0)
如果您的意思是“为什么使用数据提供者BeginExecute___()/EndExecute____()
方法而不是在委托中包装普通Execute____()
,我怀疑答案是他们第一次为ado.net设计提供者模型时对于.Net 1.0,在委托中包装内容并异步调用它并不是那么简单。
其他可能的原因是,这与原始.Net的旧代码更新或包装的工作方式相匹配,或者内置方法允许您轻松检查任何返回的异常