Поддержка отчетов о прогрессе и дополнительных результатов в .NET 4.0 "Task Parallel Library" - PullRequest
15 голосов
/ 08 октября 2009

Я знаю, что Task Parallel Library все еще находится в бета-версии, и, вероятно, будет меньше доступных ресурсов, но из всего, что я прочитал, библиотека дает очень особый подход к планированию задач обработка исключений и отмена .

Но я не нахожу никаких ссылок на отчеты о ходе выполнения и отправки дополнительных результатов из задач. Эти 2 вещи кажутся слишком важными, чтобы их игнорировать. Можете ли вы пролить свет на то, как обращаться с ними в Task Parallel Library, или сослаться на некоторые статьи, которые их объясняют?

Ответы [ 5 ]

9 голосов
/ 08 октября 2009

В этом примере обновляется индикатор выполнения:

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++; });   
            });   
        });   
    }   
}  

Обновление индикатора выполнения изнутри Parallel.For

8 голосов
/ 15 декабря 2011

Это один из моих лучших результатов поиска и до сих пор нет примера прогресса в Task Parallel Library прямо здесь ...

Сегодня я только что наткнулся на TPL, потому что хочу разработать новое многопоточное приложение, но без использования BackgroundWorker (потому что я где-то читал о задаче с хорошим кодом)

Я скомпилировал пример из ответа @Stephen Cleary, его ссылка довольно сложна для поиска прогресса и некоторых других сайтов.

Это очень простой пример того, как сделать Прогресс и Завершено безопасным для UI способом:

        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 секунд, а затем добавить «Готово!» строка в строке заголовка окна формы. Вы можете видеть, что TaskScheduler - хитрый способ создания безопасного обновления потока пользовательского интерфейса, поскольку я думаю, что задача запланирована для запуска в основном потоке.

7 голосов
/ 18 марта 2010

Для этого нет встроенной поддержки, как у BackgroundWorker.

Вы можете использовать SynchronizationContext напрямую; здесь есть отличное видео: http://www.rocksolidknowledge.com/ScreenCasts.mvc/Watch?video=TasksAndThreadAffinity.wmv

Автор развивает два решения в этом видео: одно с использованием SynchronizationContext, а другое с помощью продолжения задач. Для вашей проблемы продолжения не будут работать, но подход SynchronizationContext будет работать нормально.

P.S. Если вы создаете код многократного использования, то при захвате SynchronizationContext.Current вы должны проверить на нулевое значение и (если он нулевой) вместо этого использовать созданный по умолчанию SynchronizationContext.

ОБНОВЛЕНИЕ : я разместил код для этого в своем блоге . Мое решение на самом деле основано на Task, который запланирован обратно в поток пользовательского интерфейса с помощью TaskScheduler, который использует SynchronizationContext внизу. В отличие от принятого ответа, это решение будет работать как для WPF, так и для Windows Forms.

2 голосов
/ 08 октября 2009

TPL не особо ориентирован на поддержку пользовательского интерфейса, вы можете (все еще) использовать BackgroundWorker для этого. Что касается отправки или обработки промежуточных результатов, существуют новые классы коллекций (ConcurrentQueue) для поддержки этого.

0 голосов
/ 23 апреля 2014

Чтобы сообщить о выполнении асинхронной задачи, передайте IProgress в асинхронный метод. Внутри метода вызовите Report с данными о ходе выполнения. Вызывающий может решить, как обрабатывать этот отчет о ходе выполнения (то есть игнорировать его или обновить пользовательский интерфейс).

...