繁体   English   中英

在UI线程上运行的TPL数据流块

[英]TPL Dataflow Blocks Running On UI Thread

我正在构建一个数据流管道来进行各种处理(主要是I / O,但有些CPU处理),这是自然发生的流程。 该流程目前处于这种基本模式:

  1. 从文件加载数据
  2. 使用变换块解析记录
  3. 通过REST序列化并将对象上传到服务器

该处理管道可以自动启动,也可以通过GUI启动。 当它从GUI启动时,我想向最终用户提供进度消息。 如果我在步骤1和2之间添加一个BufferBlock ,在步骤3之后添加一个ActionBlock并设置它们的选项以在与UI相同的线程上运行,那么其他块是否仍然使用自己的线程BufferBlock运行UI?

我正在查看这篇MSDN文章: http//msdn.microsoft.com/en-us/library/hh228605( v = vs.110).aspx,但对于这种行为并不是很清楚。 我可以从可以在UI线程上运行的管道中触发事件来完成此操作吗?

编辑:管道将从UI上的BackgroundWorker对象启动,而不是直接从UI线程启动。

感谢Noseratio的建议,我实际上重新设计了它是如何完成的,并且能够让它在没有问题的情况下工作。 我删除了BackgroundWorker对象,因为它不是必需的。 相反,我将整个数据流包装在一个异步方法中,该方法将各种Progress<T>参数作为进度更新的回调。 由于Progress<T>Report()方法在预先存在的块中被调用,因此没有额外的TPL块用于发布进度。 此外,由于这是一个异步函数,表示数据流的Task不在UI线程上运行,而是在线程池线程上运行。 从中可以看出, Progress<T>对象的回调是在它们创建的线程上运行的,因为在构造过程中它们捕获当前的同步上下文。 以下是解决我的问题的示例:

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
}


然后在UI中创建了Progress<int>对象并将它们传递给异步ProcessData方法。 每当在异步处理方法中调用Process<T>.Report()方法时,UI都会更新而不会出现问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM