如何监控 TPL 数据流网格中的进度? [英] How do I monitor progress in a TPL Dataflow mesh?

查看:31
本文介绍了如何监控 TPL 数据流网格中的进度?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个 C# 应用程序,该应用程序具有必须异步执行的耗时顺序工作流.它在用户按下按钮时启动,应用程序在几毫秒内接收到从相机捕获的一些图像.然后是工作流程.

I'm working on a C# app with a time-consuming sequential workflow that must be performed asynchronously. It starts when the user presses a button and the app receives a few images captured from a camera within just a few milliseconds. The work flow then.

  1. 将图像保存到磁盘
  2. 对齐它们.
  3. 从它们生成 3d 数据.
  4. 将它们组合成一个更大的集体对象(称为扫描").
  5. 向此扫描添加可选的分析数据并执行它.
  6. 最终保存扫描本身与图像一起保存到一个 xml 文件中.

其中一些步骤是可选和可配置的.

Some of these steps are optional and configurable.

由于处理可能需要很长时间,因此通常会有一个等待处理的扫描"队列所以我需要向用户呈现捕获扫描队列的视觉表示,它们当前的处理状态(例如正在保存"、分析"、完成"等)

Since the processing can take so long, there will often be a queue of "scans" awaiting processing So I need to present to a user a visual representation of the queue of captured scans, their current processing state (e.g. "Saving", "Analyzing", "Finished" etc.)

我已经研究过为此使用 TPL DataFlow.但是,虽然网格很容易创建,但我并没有了解如何监控正在发生的事情的状态,以便我可以更新用户界面.我是否尝试将用于回发消息的自定义操作块链接到 UI?还有什么?

I've looked into using TPL DataFlow for this. But while the mesh is simple to create, I'm not getting just how I might monitor the status of what is going on so that I can update a user interface. Do I try to link custom action blocks that post back messages to the UI for that? Something else?

TPL Dataflow 是否是完成这项工作的正确工具?

Is TPL Dataflow even the right tool for this job?

推荐答案

报告整体进展

当您考虑到 TPL 数据流图具有开始和结束块并且您知道发布到图中的项目数量时,您需要做的就是跟踪到达最终块的消息数量并将其与源进行比较发布到头部的消息计数.这将允许您报告进度.

Reporting Overall Progress

When you consider that a TPL DataFlow graph has a beginning and end block and that you know how many items you posted into the graph, all you need do is track how many messages have reached the final block and compare it to the source count of messages that were posted into the head. This will allow you to report progress.

现在,如果块是 1:1,这很简单——也就是说,对于任何消息,都有一条消息输出.如果有一个:多个块,您需要相应地更改您的进度报告.

Now this works trivially if the blocks are 1:1 - that is, for any message in there is a single message out. If there is a one:many block, you will need to change your progress reporting accordingly.

如果您希望在整个图表中显示作业的进度,您需要将作业详细信息传递给每个块,而不仅仅是实际块所需的数据.工作是一项必须跨越问题中列出的所有步骤 1-6 的单一任务.

If you wish to present progress of a job as it travels throughout the graph, you will need to pass job details to each block, not just the data needed for the actual block. A job is a single task that must span all the steps 1-6 listed in your question.

例如步骤2可能需要图像数据来执行对齐,但它不关心文件名;工作或其他任何与工作相关的步骤有多少个步骤.没有足够的细节来了解当前作业的状态,或者仅根据块输入很难查找原始作业.您可以参考一些外部字典,但最好将图形设计为孤立的并且仅处理传递到每个块中的数据.

So for example step 2 may require image data in order to perform alignment but it does not care about filenames; how many steps there are in the job or anything else job related. There is insufficient detail to know state about the current job or makes it difficult to lookup the original job based on the block input alone. You could refer to some external dictionary but graphs are best designed when they are isolated and deal only with data passed into each block.

所以一个简单的例子是改变这个最小的代码:

So a simple example would be to change this minimal code from:

var alignmentBlock = new TransformBlock<Image, Image>(n => { ... });

...到:

var alignmentBlock = new TransformBlock<Job, Job>(x => 
{
     job.Stage = Stages.Aligning;

     // perform alignment here
     job.Aligned = ImageAligner.Align (x.Image, ...);

     // report progress 

     job.Stage = Stages.AlignmentComplete;
});

...并为其他块重复该过程.

...and repeat the process for the other blocks.

舞台属性可以触发 PropertyChanged 通知或使用适合您的 UI 的任何其他形式的通知模式.

The stage property could fire a PropertyChanged notification or use any other form of notification pattern suitable for your UI.

现在你会注意到我引入了一个 Job 类,它作为唯一的参数传递给每个块.Job 包含块的输入数据以及块输出的容器.

Now you will notice that I introduce a Job class that is passed as the only argument to each block. Job contains input data for the block as well as being a container for block output.

现在这会起作用,但我的纯粹主义者认为最好将作业元数据分开,什么是 TPL 块输入和输出,否则多线程可能会损坏状态.

Now this will work, but the purist in me feels that it would be better to perhaps keep job metadata separate what is TPL block input and output otherwise there is potential state damage from multiple threads.

为了解决这个问题,您可能需要考虑使用 Tuple<> 并将其传递到块中.

To get around this you may want to consider using Tuple<> and passing that into the block.

例如

var alignmentBlock = new TransformBlock<Tuple<Job, UnalignedImages>, 
                                        Tuple<Job, AlignedImages>>(n => { ... });

这篇关于如何监控 TPL 数据流网格中的进度?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆