Зачем нам нужен метод ContinueWith? - PullRequest
18 голосов
/ 24 июня 2011

Зачем нам нужен Task.ContinueWith() метод. Разве мы не можем просто написать этот «код продолжения» в теле задачи?

Ответы [ 3 ]

10 голосов
/ 16 января 2012

Саша Гольдштейн ответ правильный.Существуют случаи, когда ваш код композиции продолжения не имеет прямого доступа или даже не устанавливает метод выполнения задачи.Подключаемая система, которая хочет агрегировать такты, например.

Однако может быть другая причина.Гранулярность

Рассмотрите требования, которые могут спровоцировать использование TaskCreationOptions.LongRunning .В параллельной системе, где многие сотни процессов планируются, выполняются и завершаются, планировщик задач работает для обеспечения эффективного соответствия процессоров при планировании задач.

Если вы находитесь в ситуации, когда вы можете разбить задачув мелкозернистые подзадачи и их цепочку, вам больше не нужно будет использовать TaskCreationOptions.LongRunning .Проще говоря, это будет работать лучше, потому что легче запланировать 100 небольших задач для одновременного завершения, чем запланировать 10 больших задач, чтобы сделать то же самое в среде, где доступно только 4 ядра.Помните, что цепочечное задание не гарантировано запускается сразу после того, как оно предшествовало.

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

Если вы спросите меня, вы должны использовать ContinueWith (), где это возможно, так как это поможет масштабировать ваше приложение.

9 голосов
/ 24 июня 2011

Иногда вы получаете задание извне и хотите связать свое продолжение с ним. Существуют также способы создания задачи без действия (например, с помощью TaskCompletionSource).

5 голосов
/ 24 июня 2011

Продолжения задач позволяют вам создавать цепочки задач, за каждой задачей в цепочке следует еще одна задача

Также в методе Task.ContinueWith вы можете асинхронно проверять Task с помощью TaskContinuationOptions, когда цель Task завершается или возникает ошибка

Task task = Task.Factory.StartNew
(
    () =>
        {
            //Your action when the task started
        }
);

task.ContinueWith
(
    _ =>
        {   
            //Your action when the task completed
        },
    CancellationToken.None,
    TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.AttachedToParent,
    TaskScheduler.FromCurrentSynchronizationContext()
);

task.ContinueWith
(
    (t) =>
        {
            //Action when error occured
            Exception exception = null;

            if (t.Exception.InnerException != null)
            {
            exception = t.Exception.InnerException;
            }
            else
            {
            exception = t.Exception;
            }

            //You can use this exception
        },
    CancellationToken.None,
    TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.AttachedToParent,
    TaskScheduler.FromCurrentSynchronizationContext()
);

Для получения дополнительной информации смотрите здесь

...