用于长查询的.NET线程解决方案
Senerio
我们有一个记录事件的C#.Net Web应用程序。 当事件得到主管批准时,需要查询外部数据库。 对此外部数据库的查询有时需要一段时间才能运行。 这种滞后是通过浏览器体验的。
可能解决方案
我想使用线程来消除模拟的浏览器挂起。 我之前使用过Thread
类并听说过ThreadPool
。 但是,我刚在这篇文章中找到了BackgroundWorker
。
MSDN声明 :
BackgroundWorker类允许您在单独的专用线程上运行操作。 下载和数据库事务等耗时的操作可能会导致用户界面(UI)在运行时停止响应。 当您需要响应式UI并且遇到与此类操作相关的长时间延迟时,BackgroundWorker类提供了一种方便的解决方案。
在处理长时间运行的查询时, BackgroundWorker
是否可行?
当同时运行2个或更多BackgroundWorker
进程时会发生什么? 它像游泳池一样处理吗?
是的, BackgroundWorker可以显着简化您的长线操作的线程代码。 关键是注册DoWork , ProgressChanged和RunWorkerCompleted事件。 这些可以帮助您避免必须与线程来回传递一堆同步对象,以尝试确定操作的进度。
此外,我相信在UI线程上调用进度事件,从而无需调用Control.Invoke来更新UI。
要回答您的上一个问题,是的,线程是从.NET线程池分配的,因此您可以根据需要实例化任意数量的BackgroundWorker对象,但只能运行与线程池允许的并行操作数。
如果您正在使用.NET 4(或者可以使用Rx Framework中的TPL 反向端口 ),那么一个不错的选择是使用使用LongRunning提示创建的任务 。
这提供了许多难以通过ThreadPool或BackgroundWorker完成的选项,包括允许在创建时指定延续,以及允许干净的取消和exception/error handling。
对于长时间运行的查询,我遇到了类似的情况。 我使用了委托提供的异步调用。 您可以使用委托的BeginInvoke方法。
BackgroundWrokerks就像任何其他线程一样,接受它们可以被杀死或退出,不会退出主线程和你的应用程序。
ThreadPool使用BackgroundWorkers池。 它是大多数multithreading场景的首选方式,因为.net为您管理线程,并重新使用它们而不是根据需要创建新线程,这是一个昂贵的过程。
这种线程场景非常适合处理器密集型代码。
对于外部发生的查询,您还可以选择异步数据访问。 您可以移交查询请求,并为其指定回调方法的名称,该方法将在查询完成时调用,而不是对结果执行某些操作(即更新UI状态或显示返回的数据)。
.Net内置了对异步数据查询的支持http://www.devx.com/dotnet/Article/26747