- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一个相当简单的线程问题。
我正在编写一个简单的实用程序,它将根据用户定义的参数运行各种 SQL 脚本。
为了保持 UI 响应并提供有关正在执行的脚本状态的反馈,我决定使用 ThreadPool.QueueUserWorkItem
来处理各种脚本(通过 SMO。)
但是,我对如何中继 SMO 将返回到 UI 线程的输出信息感到有点困惑。
对于此实用程序,我使用 WPF 和 MVVM 进行演示。我想我会有一个 ScriptWorker
类,我可以将参数和位置以及运行脚本的顺序传递给它。
在我运行每个脚本后,我想以某种方式将结果返回到 UI 线程,以便它更新输出窗口,然后我希望工作人员转到下一个任务。
我确定这是一个基本问题,但在查看 QueueUserWorkItem
并看到我实际上是通过回调开始工作后,我不确定我将如何完成我想要的喜欢完成。
我的假设基于这篇 Microsoft 文章:
http://msdn.microsoft.com/en-us/library/3dasc8as(VS.80).aspx
感谢您提供信息!
最佳答案
QueueUserWorkItem
在技术上可以工作,但级别非常低。有更简单的方法。
我建议使用 .NET 4.0 的新 Task
功能。它完全按照您的意愿行事,包括将结果或错误条件同步到另一个线程(在本例中为 UI 线程)。
如果 .NET 4.0 不是一个选项,那么我会推荐 BackgroundWorker
(如果您的后台处理不是太复杂),或者 Hans 提到的异步委托(delegate)。如果您使用异步委托(delegate),则使用 AsyncOperation
类将结果编码回 UI 线程。
Task
选项非常好,因为它可以非常自然地处理父/子任务。 BackgroundWorker
不能嵌套。另一个考虑因素是取消; Task
和 BackgroundWorker
内置了对取消的支持,但对于异步委托(delegate),您必须自己做。
Task
唯一比 BackgroundWorker
复杂一点的地方是进度报告。它不像 BackgroundWorker
那么简单,但我有一个包装器 on my blog以尽量减少这种情况。
总结一下,按优先顺序:
Task
- 支持正确的错误编码、结果概念、取消和父/子嵌套。它的一个弱点是进度报告并不简单(您必须创建另一个任务并将其安排到 UI 线程)。BackgroundWorker
- 支持正确的错误编码、结果概念、取消和进度报告。它的一个弱点是它不支持父/子嵌套,这限制了它在 API 中的使用,例如,用于业务层。Delegate.BeginInvoke
with AsyncOperation
- 支持错误的正确编码、结果的概念和进度报告。但是,没有内置的取消概念(尽管可以使用 volatile bool
手动完成)。它也不支持父/子嵌套。Delegate.BeginInvoke
with SynchronizationContext
- 这与选项 (3) 相同,只是它直接使用 SynchronizationContext
。代码稍微复杂一些,但权衡是支持父/子嵌套。所有其他限制与选项 (3) 相同。ThreadPool.QueueUserWorkItem
with AsyncOperation
或 SynchronizationContext
- 支持进度报告的概念。取消遇到与选项 (3) 相同的问题。错误的编码并不容易(特别是保存堆栈跟踪)。此外,父/子嵌套只有在使用 SynchronizationContext
而不是 AsyncOperation
时才有可能。此外,此选项不支持结果的概念,因此任何返回值都需要作为参数传递。如您所见,Task
是明显的赢家。除非 .NET 4.0 不是一个选项,否则应该使用它。
关于c# - 如何将信息从 ThreadPool.QueueUserWorkItem 传递回 UI 线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3484135/
我是一名优秀的程序员,十分优秀!