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

Как Task <int> становится int?

У нас есть этот метод:

async Task<int> AccessTheWebAsync()
{ 
    HttpClient client = new HttpClient();

   Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");

   // You can do work here that doesn't rely on the string from GetStringAsync.
   DoIndependentWork();

   string urlContents = await getStringTask;
   //The thing is that this returns an int to a method that has a return type of Task<int>
   return urlContents.Length;
}

Происходит ли неявное преобразование между Task<int> и int? Если нет, то что происходит? Как это реализовано, чтобы работать?

4b9b3361

Ответ 1

Происходит ли неявное преобразование между Task <> и int?

Нету. Это только часть того, как работает async/await.

Любой метод, объявленный как async должен иметь тип возвращаемого значения:

  • void (по возможности избегайте)
  • Task (нет результата после уведомления о завершении/сбое)
  • Task<T> (для логического результата типа T в асинхронном режиме)

Компилятор делает все необходимые переносы. Дело в том, что вы асинхронно возвращаете urlContents.Length - вы не можете заставить метод просто возвращать int, поскольку реальный метод вернется, когда он попадет в первое выражение await которое еще не завершено. Таким образом, вместо этого он возвращает Task<int> который завершится после завершения самого асинхронного метода.

Обратите внимание, что await делает противоположное - разворачивает Task<T> в значение T, как работает эта строка:

string urlContents = await getStringTask;

... но, конечно, он разворачивается асинхронно, тогда как простое использование Result блокирует, пока задача не будет завершена. (await может развернуть другие типы, которые реализуют ожидаемый шаблон, но наиболее часто вы будете использовать Task<T>.)

Эта двойная упаковка/распаковка - это то, что позволяет асинхронности быть настолько составной. Например, я мог бы написать другой асинхронный метод, который вызывает ваш и удваивает результат:

public async Task<int> AccessTheWebAndDoubleAsync()
{
    var task = AccessTheWebAsync();
    int result = await task;
    return result * 2;
}

(Или просто return await AccessTheWebAsync() * 2; конечно.)

Ответ 2

Не требует преобразования Задачи в int. Просто используйте результат задачи.

int taskResult = AccessTheWebAndDouble().Result;

public async Task<int> AccessTheWebAndDouble()
{
    int task = AccessTheWeb();
    return task;
}

Он вернет значение, если доступно, иначе вернет 0.