我正在开发一个应用程序,后台进程会运行很长一段时间,我想向UI报告进度。我想在.Net 4.0中使用任务,以便我对它们有所了解。我找到了Stephen Cleary的精彩文章,其中包含了一个类,即ProgressReporter(文章链接在底部)。
我可以直接上课并按原样使用它,但后来我不拥有这些知识。我根本无法理解的部分是关于TaskScheduler对象。我已经阅读了文档,但它假设我已经知道调度程序是什么而我实际上并不知道。
从Stephen的文章看来,如果我使用“FromCurrentSynchronizationContext”创建一个TaskScheduler,从即将启动后台任务的事件开始,那么我可以在异步进程中使用该TaskScheduler实例创建一个新任务然后可以访问UI控件,并且实际上将在UI线程上运行。
至少从干净优雅的代码看起来就是这样。
有人可以帮我理解TaskScheduler(或只是一个调度程序)是什么,以便“FromCurrentSynchronizationContext”有意义吗?
非常感谢!
引用文章的链接: http://nitoprograms.blogspot.com/2010/06/reporting-progress-from-tasks.html
答案 0 :(得分:4)
首先,要了解Task
本身与ThreadPool
无关。将Task
视为一个工作单元是有帮助的,仅此而已。它实际上只是一个花哨的代表。
TaskScheduler
可以运行Task
。默认TaskScheduler
在Task
上运行ThreadPool
,但这不是唯一的TaskScheduler
。您可以致电TaskScheduler.FromCurrentSynchronizationContext
以获取在UI线程上运行TaskScheduler
的{{1}}。
ParallelExtensionsExtras库包含几个有趣的Task
。有关详细信息,请参阅this series中的第5,6和7个帖子。
所以,回到我的TaskScheduler
课程,我正在做的是:
ProgressReporter
,它捕获将在UI线程上运行ProgressReporter
的{{1}}。TaskScheduler
(其中“背景”表示它在Task
上的默认Task
上运行)。TaskScheduler
想要报告进度时,会创建新 ThreadPool
并将其发送到用户界面Task
。我应该指出Async CTP使用的方法略有不同。他们建议需要报告进度的任务采用Task
参数(这是一个好主意)。然后他们提供了一个实现(TaskScheduler
),它在捕获的IProgress<T>
上引发了一个事件。使用EventProgress<T>
与我的SynchronizationContext
类似,但有两个重要区别:
EventProgress<T>
方法让使用者定义对进度更新的响应。我的ProgressReporter
有生产者(后台操作)定义了对进度更新的响应。IProgress<T>
将立即返回,允许后台操作继续。默认情况下,ProgressReporter
将等待UI更新。 IProgress<T>
是更好的设计,因为第一点(尽管我认为ProgressReporter
在使进度报告同步时更正确)。 IProgress<T>
当时很好,并且可以敲出一些快速代码,但是如果你正在设计一个可重复使用的背景组件,请使用与ProgressReporter
类似的东西。
如果您不熟悉Async CTP,我强烈建议您查看它。它还没有为生产使用做好准备,但你至少应该阅读“基于任务的异步模式”的论文。它显示了事情的进展,并且是设计使用ProgressReporter
s的API的经过深思熟虑的方法。
P.S。我上面做了几个简化:
IProgress<T>
只是一个工作单位,甚至不是一个“花哨的代表”。实际上,工作单元实际上可以由另一个程序完成,在这种情况下,根本没有委托附加到Task
对象。您可以使用Task
类创建这些抽象的“工作单元”。Task
或者为什么用它来安排UI的工作。从本质上讲,它是一个“委托调度程序” - 如果您将委托视为“工作单元”,可以使用TaskCompletionSource
来运行委托。更多信息将在下周的MSDN 2月刊中发布。