В чем разница между ожиданием Task <T> и Task <T>.Result?
public async Task<string> GetName(int id)
{
Task<string> nameTask =
Task.Factory.StartNew(() => { return string.Format("Name matching id {0} = Developer", id); });
return nameTask.Result;
}
В приведенном выше методе return return я использую свойство Task.Result.
public async Task<string> GetName(int id)
{
Task<string> nameTask =
Task.Factory.StartNew(() => { return string.Format("Name matching id {0} = Developer", id); });
return await nameTask;
}
Здесь я использую ожидание задачи. Я не ошибусь, если я думаю, что ожидание освободит вызывающий поток, но Task.Result заблокирует его, было бы правильно?
Ответы
Ответ 1
Я не ошибусь, если я думаю, что ожидание освободит вызывающий поток, но Task.Result заблокирует его, было бы правильно?
Как правило, да. await task;
будет "выводить" текущий поток. task.Result
заблокирует текущий поток. await
- асинхронное ожидание; Result
является ожидающим блокировки.
Еще одно незначительное отличие: если задача завершается в неисправном состоянии (т.е. с исключением), то await
будет (повторно) возбуждать это исключение как есть, но Result
будет обертывать исключение в AggregateException
.
В качестве побочного примечания избегайте Task.Factory.StartNew
. Это почти никогда не правильный метод для использования. Если вам нужно выполнить работу над фоновым потоком, предпочитайте Task.Run
.
Оба Result
и StartNew
подходят, если вы выполняете динамическую задачу parallelism; в противном случае их следует избегать. Не подходит, если вы выполняете асинхронное программирование .
Ответ 2
Я не ошибусь, если я думаю, что ожидание освободит вызывающий поток, но Task.Result заблокирует его, было бы правильно?
Вы правы, если задача не завершилась синхронно. Если это так, использование Task.Result
или await task
будет выполняться синхронно, так как await
сначала проверит, завершилась ли задание. В противном случае, если задача не завершилась, она заблокирует вызывающий поток для Task.Result
, а при выполнении await
будет a синхронно ждать для завершения задач. Другое отличие от обработки исключений. В то время как первый будет распространять AggregationException
(который может содержать одно или несколько исключений), последний разворачивает его и возвращает основное исключение.
В качестве побочного примечания с использованием асинхронных оберток по методам синхронизации является плохой практикой и его следует избегать. Также, используя Task.Result
внутри асинхронного метод является причиной взаимоблокировок, и его также следует избегать.