Блоки потока данных TPL, работающие в потоке пользовательского интерфейса
Я строю конвейер потока данных для выполнения различных операций обработки(в основном ввода-вывода, но некоторые операции процессора), которые находятся в естественном потоке. Поток в настоящее время находится в этой основной схеме:
- загрузка данных из файла
- разбор записи с помощью блока преобразования
- сериализация и загрузка объекта на сервер через REST
Этот конвейер обработки может быть запущен автоматически или через графический интерфейс пользователя. Для того, когда он запускается из GUI, я хотел бы предоставить сообщения о ходе выполнения для конечный пользователь. Если я добавлю BufferBlock между шагами 1 и 2 и ActionBlock после шага 3 и задам параметры для их запуска в том же потоке, что и пользовательский интерфейс, будут ли другие блоки по-прежнему запускаться из пользовательского интерфейса, используя свой собственный пул потоков?
Я смотрел на эту статью MSDN: http://msdn.microsoft.com/en-us/library/hh228605 (v=против 110).aspx , но это было не очень ясно относительно такого поведения. Могу ли я запустить событие из конвейера, которое также может выполняться в потоке пользовательского интерфейса, чтобы выполнить это?
Править: Конвейер будет запущен из объекта BackgroundWorker в пользовательском интерфейсе, а не непосредственно из потока пользовательского интерфейса.
1 ответ:
Благодаря предложениям Noseratio я фактически переработал, как это делается, и смог заставить его работать без проблем. Я устранил объект
BackgroundWorker, так как в этом не было необходимости. Вместо этого я обернул весь поток данных в асинхронный метод, который принимает различные параметрыProgress<T>в качестве обратных вызовов для обновления хода выполнения. Не было никаких дополнительных блоков TPL, используемых для пост-прогресса, так как методProgress<T>'sReport()вызывается внутри уже существующих блоков. Кроме того, так как это асинхронно функция задача, представляющая поток данных, выполняется не в потоке пользовательского интерфейса, а в потоке 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>и передал их в метод asyncProcessData. Всякий раз, когда методProcess<T>.Report()были вызваны в методе асинхронной обработки пользовательский интерфейс обновляется без проблем.
Comments