2016-03-10 12 views
1

У меня есть Task<T> t1. Я хочу запустить еще один Task t2 после завершения t1. Я предпочитаю использовать метод .ContinueWitht1.Почему ContinueWith передает задачу как параметр

void ThenFrob(Task<Frobber> t1) { 
    t1.ContinueWith(frobber => frobber.Frob()) 
} 

Кроме этого, я не могу этого сделать, потому что параметр Действия Task<T> передается Task<T>, а не сам T. Вместо этого я должен принять результат параметра, переданного в мое действие, чтобы взаимодействовать с ним.

void ThenFrob(Task<Frobber> t1) { 
    t1.ContinueWith(frobberTask => { 
     var frobber = frobberTask.Result; 
     frobber.frob(); 
    }); 
} 

Если точка ContinueWith является добавление другого действия в цепи, то почему бы не разработчики языка просто прошли результат предыдущей задачи? Или, в случае неосновной Задачи, ожидается действие без параметров?

+1

Что является результатом предыдущей задачи, если исключение задачи выбрано? – PetSerAl

+0

Мышление в соответствии с непараллельной разработкой или обещаниями, я ожидал бы другую подпись метода для обработки исключений. ContinueWith означает, что предыдущая задача завершена, а не ошибка. – psaxton

+1

BTW, я думаю, что лучше использовать 'ContinueWith (async t => {var result = await t ...})', а не '.Result', даже для самого маленького риска, что кто-то скопирует-вставьте действие во внешний код, где '.Result' может блокировать поток. –

ответ

2

ContinueWith запускает делегата, когда задача входит в состояние task.IsCompleted == true. Не когда он входит в состояние task.IsCompleted == true && task.IsFaulted == false && task.IsCanceled == false, задача, которая забросила исключение или отмененную задачу, как «завершена», так и не приведет к результату.

Есть перегрузки вы можете передать в TaskContinuationOptions как TaskContinuationOptions.OnlyOnRanToCompletion, чтобы получить поведение, как вы описываете, но это будет более сложным, чтобы иметь Action<T> перегрузку только для этого один варианта перечисления так что они просто используют общую перегрузку Action<Task<T>> так вам может использовать тот же метод, если вы делаете OnlyOnRanToCompletion, или если вы делаете OnlyOnFaulted.

Также есть еще полезная информация в Task объекта завершенного задания, если вы используете AsyncState свойство передавать метаданные вместе, если завершена задача не была передана ContinueWith вы бы не способ получить эти данные если вы не использовали переменный захват выражения lambada.