.NET Framework 4.0: объединение задач в цикл - PullRequest
4 голосов
/ 30 марта 2011

Я хочу соединить несколько Task с, чтобы по окончании началось следующее. Я знаю, что могу сделать это, используя ContinueWith. Но что, если у меня есть большое количество задач, так что:

t1 продолжается с t2

t2 продолжается с t3

t3 продолжается с t4

...

Есть ли хороший способ сделать это, кроме создания этой цепочки вручную с помощью цикла?

Ответы [ 2 ]

6 голосов
/ 30 марта 2011

Итак, если у вас есть какое-то перечисляемое число Action делегатов или что-то, что вы хотите сделать, вы можете легко использовать LINQ для выполнения следующих действий:

// Create the base task.  Run synchronously.
var task = new Task(() => { });
task.RunSynchronously();

// Chain them all together.
var query = 
    // For each action
    from action in actions

    // Assign the task to the continuation and
    // return that.
    select (task = task.ContinueWith(action));

// Get the last task to wait on.
// Note that this cannot be changed to "Last"
// because the actions enumeration could have no
// elements, meaning that Last would throw.
// That means task can be null, so a check
// would have to be performed on it before
// waiting on it (unless you are assured that
// there are items in the action enumeration).
task = query.LastOrDefault();

Приведенный выше код действительно является вашим цикломПросто в причудливой форме.Он делает то же самое в том, что он берет предыдущую задачу (после того, как заполнен фиктивным «noop» Task), а затем добавляет продолжение в виде ContinueWith (назначая продолжение текущей задаче в процессе дляследующая итерация цикла, которая выполняется при вызове LastOrDefault).

3 голосов
/ 30 марта 2011

Вы можете использовать статические расширения ContinueWhenAll здесь .

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


Обновление

Вы можетеиспользуйте расширение цепочки, например:

public static class MyTaskExtensions
{
    public static Task BuildChain(this Task task, 
        IEnumerable<Action<Task>> actions)
    {
        if (!actions.Any())
            return task;
        else
        {
            Task continueWith = task.ContinueWith(actions.First());
            return continueWith.BuildChain(actions.Skip(1));
        }
    }
}
...