2014-08-29 4 views
0

Предположим, что следующий метод определен:Должен ли я использовать обычную задачу или задачу продолжения?

Task<TResult> DoStuffAsync() 
{ 
    // ... 
} 

Рассмотрим следующий код (сниппета 1):

void MyFunction() 
{ 
    Task<TResult> task = DoStuffAsync(); 
    task.ContinueWith(async() => { 
     TResult result = await task; 
     // do stuff with result 
    }); 
    // poll `task` status... 
} 

по сравнению со следующим кодом (фрагмент 2):

void MyFunction() 
{ 
    Task<TResult> task = DoStuffAsync(); 
    Task.Run(async() => { 
     TResult result = await task; 
     // do stuff with result 
    }); 
    // poll `task` status... 
} 

(Обратите внимание, что меня не волнует статус лямбда-функции (огонь и забухание). Но I do заботиться, если это r . АЙСы любые исключения)

Первое различие между этими двумя вариантами представляется очевидным: в (фрагмент 1) код в лямбда будет только начать выполнение послеDoStuffAsync() завершена, в то время как в (фрагмент 2) кода в lambda попытается немедленно начать выполнение и продолжить, когда DoStuffAsync() завершено.

Однако, помимо этой разницы, когда вы должны использовать ContinueWith и когда вы должны использовать Task.Run? Что произойдет, если исключение возникает в DoStuffAsync() или в функции лямбда? Будет ли это проглочено или все потенциальные исключения гарантированно будут подняты до блока, где он может быть обработан?

+0

Во-первых, вы не должны запрашивать статус задачи после запуска. Это довольно большой красный флаг. – Servy

+1

зачем вам это нужно? просто делать результат = ждать DoStuffAsync(); казалось бы, лучший вариант. – ths

ответ

2

В вашем первом случае нет необходимости в лямбда async. Задача не нужна await. Вы можете просто использовать Result, потому что знаете, что задача уже завершена к этому моменту времени.

Для вашего второго примера вы планируете поток потока потоков для выполнения создания конечного автомата, который будет просто планировать некоторый код для запуска, когда задача завершается. В этом нет никакой реальной необходимости. Task.Run ничего не добавляет.

Скорее всего, сам метод должен быть async метод:

private async Task MyFunction() { 
    var result = await DoStuffAsync(); 
    // do stuff with result 
} 

Все, что сказал, в то время как ваши решения имеют много лишней работы, как будут распространяться исключения из вашей основной работы с задачами, каждая операция вычисляет (хотя вы не храните эту задачу нигде в своем первом примере, так что у вас нет возможности проверить эту задачу, чтобы увидеть, не сработала ли она).

Смежные вопросы