c# - TPL 数据流 block 在 UI 线程上运行

标签 c# multithreading user-interface dataflow tpl-dataflow

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

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

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

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

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

最佳答案

多亏了 Noseratio 的建议,我实际上重新设计了它是如何完成的,并且能够让它正常工作。我消除了 BackgroundWorker对象,因为它不是真正必要的。相反,我将整个数据流包装在一个异步方法中,该方法采用各种 Progress<T>参数作为进度更新的回调。自 Progress<T> 以来,没有使用额外的 TPL block 来发布进度的 Report()方法在预先存在的 block 中调用。此外,由于这是一个异步函数,表示数据流的任务不在 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 更新的异步处理方法中调用了方法,没有问题。

关于c# - TPL 数据流 block 在 UI 线程上运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22723495/

相关文章:

c# - 如何更改 Sitecore 登录页面上的消息?

c# - ASP.NET MVC 多复选框

c# - ASP.NET 身份工厂模式是否会破坏 EntityFramework DbContext?

java - websphere中的多线程

Java 屏幕截图 - JFrame 绘制旧组件一秒钟并消失,即使所有组件都已删除并重新绘制

c# 和捕获异常

c# - 动态绑定(bind)注入(inject)

c# - 在另一个线程上创建 WPF 进度窗口

c++ - 寻找一个 C++ GUI 库,您可以在其中设计精美的 GUI(例如游戏),

xcode - 您可以在没有按钮的情况下以编程方式关闭 View Controller 吗? - 操作系统