Показ текущего статуса нескольких процессов запущенных через Parallel.ForEach

Посредством такой конструкции

Parallel.ForEach(_targetTable.Rows.Cast<DataRow>(), ReadData);

запускается несколько процессов обработки, параметры которой переданы в таблице _targetTable. Нужно вывести в окне приложения статус для каждого процесса (например, запрос данных, получение данных, обработка результатов, сохранение), сам прогресс (проценты) не нужны. Прочитал, что можно воспользоваться интерфейсом

IProgress<T>

но все примеры только для одного потока. Подскажите пожалуйста, как можно организовать вывод текущего статуса для всех потоков?

Спасибо


Ответы (1 шт):

Автор решения: aepot

Согласно документации, вызов колбэка IProgress осуществляется с перенаправлением в SynchronizationContext того потока, который его создал. Следовательно, он является своего рода потокобезопасным способом отчитываться о прогрессе.

Any handler provided to the constructor or event handlers registered with the ProgressChanged event are invoked through a SynchronizationContext instance captured when the instance is constructed.

Поэтому, вы можете просто создать поле типа IProgress, записать туда экземпляр класса Progress с коллбэком, и все должно заработать, независимо от того, в одном потоке будет выполняться итератор, или в нескольких.

Можно реализовать через поле

private readonly IProgress<string> _myProgress = new Progress(s =>
{
    Status = s; // предположим, что к Status привязан TextBlock через Binding
});

или через свойство с "ленивой" инициализацией

private IProgress<string> _myProgress;

public IProgress<string> MyProgress => _myProgress ?? (_myProgress = new Progress(s =>
{
    Status = s;
}));

Только лучше убедиться, что первое обращение к MyProgress будет из UI потока.

ну или свойство без ленивой инициализации

public IProgress<string> MyProgress { get; } = new Progress(s =>
{
    Status = s;
});

А внутри итератора просто вызывайте Report().

private void ReadData(DataRow dataRow)
{
    MyProgress.Report("my status");
}

Через IProgress можно передавать объект любого типа, не обязательно строку.

→ Ссылка