Запуск нескольких последовательностей задач поочередно с использованием TPL - PullRequest
2 голосов
/ 18 марта 2011

У меня есть класс, который возвращает IEnumerable. Затем я выполняю эти задачи по порядку. Допустим, класс - TaskProvider.

public class TaskProvider {
  public IEnumerable<Task> SomeThingsToDo() { return work; }
}

Я выполняю это со следующим:

public void ExecuteTasks(IEnumerable<Task> tasks)
{
    var enumerator = tasks.GetEnumerator();
    ExecuteNextTask(enumerator);
}

static void ExecuteNextTask(IEnumerator<Task> enumerator)
{
    bool moveNextSucceeded = enumerator.MoveNext();

    if (!moveNextSucceeded) return;

    enumerator
        .Current
        .ContinueWith(x => ExecuteNextTask(enumerator));
}

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

Тогда, самое главное, мне нужно знать, когда все задачи будут выполнены.

Какой способ TPL это сделать?

(FWIW, я использую Async CTP для Silverlight.)

Ответы [ 2 ]

1 голос
/ 18 марта 2011

Вот подход, который я выбрал, и пока все мои тесты проходят успешно.

Сначала я создал объединенное множество всех задач от различных провайдеров:

var tasks = from provider in providers
            from task in provider.SomeThingsToDo()
            select task;

IПолагаю, что частью моей первоначальной проблемы было то, что я создал ToList (более или менее) и, таким образом, начал выполнение задач преждевременно.

Затем я добавил обратный вызов в ExecuteTasks и ExecuteNextTask.Правда, не так чисто, как я надеялся.Вот пересмотренная реализация:

public void ExecuteTasks(IEnumerable<Task> tasks, Action callback)
{
    var enumerator = tasks.GetEnumerator();
    ExecuteNextTask(enumerator, callback);
}

static void ExecuteNextTask(IEnumerator<Task> enumerator, Action callback)
{
    bool moveNextSucceeded = enumerator.MoveNext();

    if (!moveNextSucceeded)
    {
        if (callback != null) callback();
        return;
    }

    enumerator
        .Current
        .ContinueWith(x => ExecuteNextTask(enumerator, callback));
}

Мне не нужна поточно-ориентированная структура для хранения списка задач, потому что список генерируется только один раз.

0 голосов
/ 18 марта 2011

в худшем случае у вас может быть статический параллельный очереди Ienumerables, который вы выполняете методом ExecuteNextTask, который проходит через ...

что-то вроде:

public static class ExecuteController {

    private static ConcurrentQueue<IEnumerable<Task>> TaskLists = new ConcurrentQueue<IEnumerable<Task>>();

    public void ExecuteTaskList(IEnumerable<Task> tasks) {
          TaskLists.Enqueue(tasks);
          TryStartExec();
    }         

    public void TryStartExec() {
         check if there is a new task list and if so exec it with your code. 
         possibly need to lock around the dequeue but i think there is an atomic dequeue method on concurrent queue..
    }

}
...