我正在开发一个Windows窗体应用程序,它在指定的时间间隔后调用WCF服务,并根据从服务接收的数据显示输出。我有一个计划为此目的使用计时器,在500毫秒后调用该WCF服务方法。但我的一些同事告诉我使用后台工作人员,然后在Work_Completed
事件重新运行工人。我想知道这两者有什么区别? timer还会创建后台线程吗?哪一个最适合长期运行的任务?
答案 0 :(得分:6)
BackgroundWorker在ThreadPool上创建一个线程(通过异步) 委托调用)。 BCL计时器使用ThreadPool线程 提高事件,或者在某些情况下会提高勾选/经过/等 UI线程上的事件(在WinForms计时器或 提供了ISynchronizeInvoke的Timers.Timer)。
BackgroundWorker为后台线程提供了最佳API UI环境。它允许一种方法在后台运行 线程(通过DoWork事件)并提供一种简单的通知方式 UI线程上的进度和完成(ProgressChanged和 RunWorkerCompleted事件),无需担心任何问题 跨线程调用。
WinForms计时器在UI线程上执行,可以安全地触摸任何一个 来自其已过去事件的UI元素。但是,您无法保证 按照确切的时间间隔执行,它完全取决于正在发生的事情 UI线程。让我重复一件重要的事情:没有 这个选项的后台线程!
Threading.Timer是一种“丑陋的API”计时器。 Timers.Timer简单 将Threading.Timer包装到更好的API中并提供了一种方法 自动调用UI线程上的已用事件(通过 SynchronizingObject属性)。如果设置SynchronizingObject 属性,没有代码在后台线程上执行,它立即获得 编组到UI线程。
通常,在UI中,BackgroundWorker更容易处理 与其他选择相比。
答案 1 :(得分:5)
在资源消耗方面,Timer
几乎肯定更合适。 BackgroundWorker
将为该任务创建一个新线程。创建新线程是一项相当昂贵的操作。虽然有许多不同的计时器实现,并且它们的实现会有所不同,但它们通常依赖于定期触发事件的OS工具,这将比启动新的专用线程更好。
Timer
对象中的大多数关键差异都是他们“准备好”时所做的事情。有些人创建了一个新的线程池线程;有些专用线程由计时器的所有实例共享以运行处理程序,有些将代码编组到UI线程(或其他一些同步上下文),而后者则是您可能想要的。如果您使用在您正在使用的特定UI框架中提供的计时器,那么您将看到的行为。
答案 2 :(得分:4)
根据我的经验,主要好处Background Worker是ProgressChanged
和RunWorkerCompleted
事件将在工作者实例化的同一线程上执行。因此,如果您在UI线程上启动后台工作程序,则RunWorkerCompleted事件也将在UI线程上触发。这使得如果您想在后台工作完成时更新UI组件,则不必担心进行非法的跨线程调用。
答案 3 :(得分:3)
标准System.Windows.Forms.Timer
应该没问题。它在UI线程上调用它的回调,这意味着当你在回调内处理时,它可能会冻结你的UI响应。但是如果你在回调中做了很多工作或者你阻止了线程,这只是一个问题。
为了避免阻塞线程,只需执行异步WCF调用。
BackgroundWorker
对你想做什么毫无意义。你要做的就是在执行一些代码之前等待500ms,所以只需使用System.Windows.Forms.Timer
。