Насколько я понимаю, если у вас есть метод async
, в котором единственным await
является окончательный возврат Task
, вы можете удалить ключевые слова async
и await
и просто верните Task
.
Например:
public async Task<object> Handle(object message)
{
var result = await Task.FromResult(message);
return result;
}
Становится
public Task<object> Handle(object message)
{
return Task.FromResult(message);
}
Однако это не работает, если метод содержит несколько операторов ожидания.
Например:
async Task Main()
{
// outputs: Request
var requestHandlerAwaitingResult = (Request) await new HandlerAwaitingResult().Handle(new Request());
Debug.WriteLine(requestHandlerAwaitingResult.Description);
// InvalidCastException: Unable to cast object of type 'System.Threading.Tasks.Task`1[System.Object]' to type 'Request'.
var requestHandlerReturnTask = (Request) await new HandlerReturningTask().Handle(new Request());
Debug.WriteLine(requestHandlerReturnTask.Description);
}
public class Request
{
public string Description = "Request";
}
public class HandlerAwaitingResult
{
public async Task<object> Handle(object message)
{
await Task.Delay(TimeSpan.FromSeconds(1));
var result = await Task.FromResult(message);
return result;
}
}
public class HandlerReturningTask
{
public async Task<object> Handle(object message)
{
await Task.Delay(TimeSpan.FromSeconds(1));
return Task.FromResult(message);
}
}
Кто-нибудь может сказать мне, почему это не работает?
По сути, в чем разница между
public class HandlerReturningTask
{
public async Task<object> Handle(object message)
{
await Task.Delay(TimeSpan.FromSeconds(1));
return Task.FromResult(message);
}
}
А также
public class HandlerReturningTask
{
public async Task<object> Handle(object message)
{
await Task.Delay(TimeSpan.FromSeconds(1));
return await Task.FromResult(message);
}
}
А также
public class HandlerReturningTask
{
public Task<object> Handle(object message)
{
return Task.FromResult(message);
}
}
2 ответа
Я все еще не уверен, что понимаю вопрос. Но на основе вашего редактирования:
По сути, в чем разница между […
return Task.FromResult(message);
…] и […return await Task.FromResult(message);
…]
Важно понимать, что делает await
: он представляет собой точку в вашем методе, из которой метод может возвращаться, а затем выполнение в методе может возобновиться позже, когда "ожидающий" (например, Task
) завершится .
Если Task
- это Task<T>
, то другая вещь, которую делает await
, - это при возобновлении выполнения в методе разворачивать значение T
для объекта Task<T>
. , т.е. получить значение его свойства Result
. Выражение await
вычисляет это значение.
Наконец, для методов async Task<T>
оператор return
заставляет объект Task<T>
, возвращаемый методом (в первом выражении await
), иметь значение Result
в Выражение return {value}
.
Итак, в вашем примере return Task.FromResult(message);
заставляет свойство Task<object>.Result
иметь значение объекта типа Task<Request>
. Позже выражение await
оценивает значение свойства этого объекта Result
, и вы пытаетесь преобразовать его в объект типа Request
, что, конечно, является незаконным.
Использование return await Task.FromResult(message);
приводит к тому, что сначала вычисляется выражение await
(поэтому оператор return
может возвращать результат этого выражения), что приводит к получению значения свойства Task<Request>.Result
. Это значение затем возвращается оператором return
, в результате чего ожидаемое значение Task<object>.Result
становится объектом Request
, первоначально переданным методу. Это, конечно, может быть приведено обратно к типу Request
при разворачивании await
в вызывающей программе.
Тем не менее, обычно вы просто возвращаете значение напрямую. Бессмысленно заключать его в объект Task<T>
только для того, чтобы сразу же развернуть его с помощью выражения await
. Написание return message;
в этом сценарии даст точно такой же результат, но с более читаемым и более эффективным кодом.
Сгенерированный конечный автомат обрабатывает все ожидаемые. Не только задачи.
Если вы имеете дело только с одной задачей, вы можете обойти накладные расходы, связанные с конечным автоматом, сгенерированным компьютером. Однако в случае исключения трассировка стека будет не такой, как вы могли бы ожидать.
Тип возврата асинхронных методов всегда будет задачей того, что вы возвращаете.
Похожие вопросы
Новые вопросы
c#
C# (произносится как «see Sharp») — это высокоуровневый мультипарадигменный язык программирования со статической типизацией, разработанный Microsoft. Код C# обычно нацелен на семейство инструментов и сред выполнения Microsoft .NET, которое включает в себя .NET, .NET Framework, .NET MAUI и Xamarin среди прочих. Используйте этот тег для ответов на вопросы о коде, написанном на C#, или о формальной спецификации C#.