4

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.

JNYRanger
  • 6,829
  • 12
  • 53
  • 81
  • Are you using `DataflowBlockOptions.TaskScheduler` to make it run an the UI thread? A piece of code would help. – noseratio Mar 29 '14 at 00:21
  • @Noseratio This is more of a theoretical question. I'm still planning this feature out. As of right now it's not reporting progress. Using the `DataflowBlockOptions.TaskScheduler` was how I was going to tell those particular blocks to run on the UI thread. – JNYRanger Mar 29 '14 at 00:43
  • 1
    I'd use the `Progress` pattern for that and did not resort to the UI thread TaskScheduler. – noseratio Mar 29 '14 at 00:45
  • @Noseratio I actually, should have been a bit more specific, it's not directly the UI thread I was thinking of using, but instead the pipeline would be started via a BackgroundWorker so it would capture the BackgroundWorker's thread's SynchronizationContext. Do you think that using `Progress` to report from the pipeline to the BackgroundWorker would be a better option, and then have the BackgroundWorker fire a progresschanged event to the UI? – JNYRanger Mar 29 '14 at 00:50
  • 2
    I think you don't need `BackgroundWorker` here. Just create `Progress` on the UI thread (it does capture the s. context and uses `sc.Post` internally). Then call it from your Dataflow pipeline wherever the progress has been made. – noseratio Mar 29 '14 at 00:54

1 Answers1

2

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.

JNYRanger
  • 6,829
  • 12
  • 53
  • 81