Блоки потока данных TPL, работающие в потоке пользовательского интерфейса



Я строю конвейер потока данных для выполнения различных операций обработки(в основном ввода-вывода, но некоторые операции процессора), которые находятся в естественном потоке. Поток в настоящее время находится в этой основной схеме:




  1. загрузка данных из файла

  2. разбор записи с помощью блока преобразования

  3. сериализация и загрузка объекта на сервер через REST


Этот конвейер обработки может быть запущен автоматически или через графический интерфейс пользователя. Для того, когда он запускается из GUI, я хотел бы предоставить сообщения о ходе выполнения для конечный пользователь. Если я добавлю BufferBlock между шагами 1 и 2 и ActionBlock после шага 3 и задам параметры для их запуска в том же потоке, что и пользовательский интерфейс, будут ли другие блоки по-прежнему запускаться из пользовательского интерфейса, используя свой собственный пул потоков?



Я смотрел на эту статью MSDN: http://msdn.microsoft.com/en-us/library/hh228605 (v=против 110).aspx , но это было не очень ясно относительно такого поведения. Могу ли я запустить событие из конвейера, которое также может выполняться в потоке пользовательского интерфейса, чтобы выполнить это?



Править: Конвейер будет запущен из объекта BackgroundWorker в пользовательском интерфейсе, а не непосредственно из потока пользовательского интерфейса.

583   1  

1 ответ:

Благодаря предложениям Noseratio я фактически переработал, как это делается, и смог заставить его работать без проблем. Я устранил объект BackgroundWorker, так как в этом не было необходимости. Вместо этого я обернул весь поток данных в асинхронный метод, который принимает различные параметры Progress<T> в качестве обратных вызовов для обновления хода выполнения. Не было никаких дополнительных блоков TPL, используемых для пост-прогресса, так как метод Progress<T>'s Report() вызывается внутри уже существующих блоков. Кроме того, так как это асинхронно функция задача, представляющая поток данных, выполняется не в потоке пользовательского интерфейса, а в потоке threadpool. Главное, что нужно из этого извлечь, - это то, что обратные вызовы объектов 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
}


Затем в пользовательском интерфейсе я создал объекты Progress<int> и передал их в метод async ProcessData. Всякий раз, когда метод Process<T>.Report() были вызваны в методе асинхронной обработки пользовательский интерфейс обновляется без проблем.

Comments

    Ничего не найдено.