Подтвердить что ты не робот

В чем разница между ожиданием 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 заблокирует его, было бы правильно?

4b9b3361

Ответ 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 внутри асинхронного метод является причиной взаимоблокировок, и его также следует избегать.