Поддержка отчетов о ходе выполнения и дополнительных результатов в .NET 4.0 «Библиотека параллельных задач»
-
20-09-2019 - |
Вопрос
я знаю это Параллельная библиотека задач все еще находится в бета-версии, и ресурсов, вероятно, будет меньше, но, судя по тому, что я читал, библиотека уделяет особое внимание планирование задач, Обработка исключений и отмена.
Но я не нашел упоминаний о отчет о ходе работы и отправка дополнительных результатов из задач.Эти две вещи кажутся слишком важными, чтобы их игнорировать.Можете ли вы пролить свет на то, как с ними обращаться в библиотеке параллельных задач, или сослаться на некоторые статьи, в которых они объясняются?
Решение
В этом примере обновляется индикатор выполнения:
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
class SimpleProgressBar : Form
{
[STAThread]
static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.Run(new SimpleProgressBar());
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
int iterations = 100;
ProgressBar pb = new ProgressBar();
pb.Maximum = iterations;
pb.Dock = DockStyle.Fill;
Controls.Add(pb);
Task.ContinueWith(delegate
{
Parallel.For(0, iterations, i =>
{
Thread.SpinWait(50000000); // do work here
BeginInvoke((Action)delegate { pb.Value++; });
});
});
}
}
Другие советы
Это один из моих лучших результатов поиска, но он до сих пор не является примером прогресса в Task Parallel Library
Прямо здесь...
Сегодня я только что наткнулся на TPL, потому что хочу разработать новое многопоточное приложение, но без использования BackgroundWorker
(потому что я раньше где-то читал о задаче с красивым кодом)
Я компилирую пример из ответа @Stephen Cleary, его ссылка довольно сложна для поиска прогресса, а также некоторых других веб-сайтов.
Это очень простой пример того, как это сделать Прогресс и Завершенный с безопасным потоком пользовательского интерфейса:
TaskScheduler currentTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task<string>.Factory.StartNew(() =>
{
// loop for about 10s with 10ms step
for (int i = 0; i < 1000; i++)
{
Thread.Sleep(10);
Task.Factory.StartNew(() =>
{
// this is a task created each time you want to update to the UI thread.
this.Text = i.ToString();
}, CancellationToken.None, TaskCreationOptions.None, currentTaskScheduler);
}
return "Finished!";
})
.ContinueWith(t =>
{
// this is a new task will be run after the main task complete!
this.Text += " " + t.Result;
}, currentTaskScheduler);
Код отобразит от 1 до 1000 в пределах 10 с, а затем добавит «Отдел!» Строка в строке заголовка формы Windows.Вы можете видеть, что TaskScheduler — это сложный способ создать потокобезопасное обновление пользовательского интерфейса, поскольку я думаю, что задача, запланированная для запуска в основном потоке.
Для этого нет встроенной поддержки, подобной той, что была в BackgroundWorker.
Вы можете использовать SynchronizationContext напрямую;здесь есть отличное видео: http://www.rocksolidknowledge.com/ScreenCasts.mvc/Watch?video=TasksAndThreadAffinity.wmv
В этом видео автор развивает два решения:один использует SynchronizationContext, а другой - продолжение задачи.Для вашей проблемы продолжения не подойдут, но подход SynchronizationContext подойдет.
P.S.Если вы создаете повторно используемый код, то при захвате SynchronizationContext.Current вам следует проверить значение null и (если оно равно null) вместо этого использовать SynchronizationContext, созданный по умолчанию.
ОБНОВЛЯТЬ:Я разместил код для этого в моем блоге.Мое решение на самом деле основано на Task
который запланирован обратно в поток пользовательского интерфейса с помощью TaskScheduler
который использует SynchronizationContext
под.В отличие от принятого ответа, это решение будет работать как для WPF, так и для Windows Forms.
TPL не особенно ориентирован на поддержку пользовательского интерфейса, вы (все еще) можете использовать для этого BackgroundWorker.Что касается отправки или обработки промежуточных результатов, для поддержки этого существуют новые классы коллекций (ConcurrentQueue).
Чтобы сообщить о ходе выполнения асинхронной задачи, передайте IPProgress в асинхронный метод.Внутри метода вызовите Отчет с данными о ходе работы.Вызывающий может решить, как обрабатывать этот отчет о ходе работы (т. е.Игнорируйте это или обновите пользовательский интерфейс).