Question

I am building a dataflow pipeline to do various processing (mostly I/O, but some CPU processing) that is in a naturally occurring flow. The flow is currently in this basic pattern:

  1. Load Data from File
  2. Parse Record using Transform Block
  3. Serialize & Upload object to server via REST

This processing pipeline can be started automatically, or via a GUI. For when it's started from the GUI I would like to provide progress messages to the end-user. If I add a BufferBlock between step 1 & 2 and an ActionBlock after step 3 and set the options for them to run on the same thread as the UI, will the other blocks still run off the UI using their own threadpool?

I was looking at this MSDN article: http://msdn.microsoft.com/en-us/library/hh228605(v=vs.110).aspx but it wasn't very clear regarding this behavior. Can I fire an event from the pipeline that can run on the UI thread as well to accomplish this?

EDIT: The pipeline would be started from a BackgroundWorker object on the UI, and not the UI thread directly.

Was it helpful?

Solution

Thanks to Noseratio's suggestions I actually redesigned how this done and was able to have it work without an issue. I eliminated the BackgroundWorker object since it wasn't really necessary. Instead I wrapped the entire dataflow in an asynchronous method, which takes various Progress<T> parameters as callbacks for progress updates. There were no extra TPL Blocks used in order to post progress since the Progress<T>'s Report() method is called within preexisting blocks. Additionally, since this is an async function the Task that represents the dataflow is not running on the UI thread, but instead on a threadpool thread. The main thing to take from this is that the Progress<T> objects's callbacks are run on the thread they are created on since during construction they capture the current synchronization context. Here is an example of what resolved my issue:

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
}


Then within the UI I created the Progress<int> objects and passed them into the async ProcessData method. Whenever the Process<T>.Report() method were called in the async processing method the UI updated without issue.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top