Продолжая несколько задач - PullRequest
0 голосов
/ 06 сентября 2011

Я использую TPL для последовательного выполнения двух задач в фоновом потоке в приложении MVVM. Во время выполнения задач приложение отображает диалоговое окно «Ход выполнения». Итак, метод Execute() моей команды MVVM сначала вызывает событие ImageProcessingStarting в модели основного вида. Представление реагирует на событие, отображая диалоговое окно Progress. Затем команда запускает первую задачу, продолжает вторую задачу и выполняет окончательное «продолжить с», вызывая событие ImageProcessingEnding в модели основного вида. Представление реагирует на событие, закрывая диалоговое окно «Ход выполнения». Код ниже.

Обе фоновые задачи выполняются правильно, но диалоговое окно «Ход выполнения» закрывается рано после завершения первой задачи, а не после второй. Я надеюсь, что кто-то может сказать мне, почему и как решить проблему. Спасибо за вашу помощь.


public void Execute(object parameter)
{
    ...

    // Announce that image processing is starting
    m_ViewModel.RaiseImageProcessingStartingEvent();

    // Set up a cancellation token source
    var tokenSource = new CancellationTokenSource();
    m_ViewModel.ProgressDialogViewModel.TokenSource = tokenSource;

    // Background Task #1: Add time stamps to files
    var task = Task.Factory.StartNew(() => this.AddTimeStampsToFiles(fileList, progressDialogViewModel));

    /* The Progress dialog is closing at this point! */

    // Background Task #2: Resequence files
    task.ContinueWith(t => this.ResequenceFiles(fileList, progressDialogViewModel));

    /* The Progress dialog should close at this point. */

    // Announce that image processing is finished
    task.ContinueWith(t => m_ViewModel.RaiseImageProcessingEndingEvent(), TaskScheduler.FromCurrentSynchronizationContext());
}

Ответы [ 2 ]

1 голос
/ 06 сентября 2011

Согласно MSDN

Метод Task.ContinueWith

Создает продолжение, которое выполняется асинхронно, когда целевая задача завершается.

Это означает, что после завершения основной задачи другие элементы в двух ваших вызовах ContinueWith будут выполняться параллельно друг другу.

Чтобы продемонстрировать это, используйте код ниже:

System.Threading.Tasks.Task task = new System.Threading.Tasks.Task(() => Console.WriteLine("1"));
task.ContinueWith((t) => { System.Threading.Thread.Sleep(1000); Console.WriteLine("2"); });
task.ContinueWith((t) => Console.WriteLine("3"));

Окно вывода будет выглядеть следующим образом:

1
3
2

Чтобы помочь вам в вашем вопросе, я всегда использовал System.ComponentModel.BackgroundWorker для последовательного запуска задач.Возможно, есть лучшие способы, но сейчас это работает для меня.

public void Execute(object parameter)
{
    BackgroundWorker bgW = new BackgroundWorker();

    bgW.DoWork += (s, args) =>
    {
        AddTimeStampsToFiles(fileList, progressDialogViewModel);
        ResequenceFiles(fileList, progressDialogViewModel);
    };

    bgW.RunWorkerCompleted += (s, args) =>
    {
        m_ViewModel.RaiseImageProcessingEndingEvent();
    }; 

    m_ViewModel.RaiseImageProcessingStartingEvent();
    bgW.RunWorkerAsync();
}

Чтобы это работало, вам может потребоваться передать значения fileList и progressDialogViewModel в метод bgW.RunWorkerAsync().

Для нескольких значений я обычно использую объект Dictionary<string, object>, поэтому могу ссылаться на значения по имени.

Надеюсь, это поможет.

0 голосов
/ 06 сентября 2011

нашел мой ответ. В моем исходном коде и вторая, и третья задачи были продолжением первой задачи. Я изменил свой код, чтобы создать отдельные задачи для исходной задачи (taskOne) и задач продолжения (taskTwo и taskThree). Затем taskTwo продолжается taskOne, а taskThree продолжается taskTwo, например:

// Background Task #1: Add time stamps to files
var taskOne = Task.Factory.StartNew(() => AddTimeStampsToFiles(fileList, progressDialogViewModel));

// Background Task #2: Resequence files
var taskTwo = taskOne.ContinueWith(t => this.ResequenceFiles(fileList, progressDialogViewModel));

// Announce that image processing is finished
var taskThree = taskTwo.ContinueWith(t => m_ViewModel.RaiseImageProcessingEndingEvent(), TaskScheduler.FromCurrentSynchronizationContext());

Я принял ответ Толстяка, поскольку он представляет собой жизнеспособную альтернативу. Тем не менее, я использую подход в этом ответе в моем приложении, так как я использую TPL.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...