我正在构建一个数据流管道来进行各种处理(主要是I / O,但是一些CPU处理),这是自然发生的流程。流程目前处于这种基本模式:
此处理管道可以自动启动,也可以通过GUI启动。当它从GUI启动时,我想向最终用户提供进度消息。如果我在第1步和第1步之间添加BufferBlock
2,在步骤3之后设置ActionBlock
并设置它们在与UI相同的线程上运行的选项,其他块是否仍然使用自己的线程池从UI运行?
我正在查看这篇MSDN文章:http://msdn.microsoft.com/en-us/library/hh228605(v=vs.110).aspx但是对于这种行为并不是很清楚。我可以从可以在UI线程上运行的管道中触发事件来完成此操作吗?
编辑:管道将从UI上的BackgroundWorker
对象启动,而不是直接从UI线程启动。
答案 0 :(得分:1)
感谢Noseratio的建议,我实际上重新设计了这样做的原因,并且能够让它在没有问题的情况下工作。我删除了BackgroundWorker
对象,因为它没有必要。相反,我将整个数据流包装在一个异步方法中,该方法将各种Progress<T>
参数作为进度更新的回调。由于在预先存在的块中调用Progress<T>
的{{1}}方法,因此没有使用额外的TPL块来发布进度。此外,由于这是一个异步函数,表示数据流的Task不在UI线程上运行,而是在线程池线程上运行。从中可以看出,Report()
对象的回调是在它们创建的线程上运行的,因为在构造过程中它们捕获当前的同步上下文。以下是解决我的问题的一个示例:
Progress<T>
然后在UI中创建了public static async Task ProcessData(IProgress<int> ReadProg, IProgress<int> UploadProg)
{
var loadBuffer = new BufferBlock<string>();
var parseBlock = new TransformBlock<string, MyObject>(async s =>
{
if(await DoSomething(s))
ReadProg.Report(1);
else
ReadProg.Report(-1);
});
...
//setup of other blocks
//link blocks
//feed data into pipeline by adding data into the head block: loadBuffer
//await ALL continuation tasks of the blocks
}
个对象,并将它们传递给异步Progress<int>
方法。每当在异步处理方法中调用ProcessData
方法时,UI都会更新而不会出现问题。