У нас есть такой метод:
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
? Если нет, то что происходит? Как это реализовано для работы?
async
ключевого слова.Ответы:
Нет. Это всего лишь часть того, как
async
/await
работает.Любой метод, объявленный как,
async
должен иметь возвращаемый тип:void
(по возможности избегайте)Task
(нет результата, кроме уведомления о завершении / неудаче)Task<T>
(для логического результата типаT
асинхронно)Компилятор выполняет все необходимые обертывания. Дело в том, что вы возвращаетесь асинхронно
urlContents.Length
- вы не можете заставить метод просто возвращатьсяint
, поскольку фактический метод вернется, когда он попадет в первоеawait
выражение, которое еще не завершено. Поэтому вместо этого он возвращает,Task<int>
который завершится, когда завершится сам асинхронный метод.Обратите внимание, что
await
происходит обратное - он разворачивает aTask<T>
вT
значение, как работает эта строка:... но, конечно, он разворачивает его асинхронно, тогда как простое использование
Result
блокирует его до тех пор, пока задача не будет завершена. (await
может разворачивать другие типы, реализующие ожидаемый шаблон, ноTask<T>
это тот, который вы, вероятно, будете использовать чаще всего.)Эта двойная упаковка / развертывание - это то, что позволяет async быть настолько компонуемым. Например, я мог бы написать еще один асинхронный метод, который вызывает ваш и удваивает результат:
(Или просто
return await AccessTheWebAsync() * 2;
конечно.)источник
async
/,await
и я считаю это крайне не интуитивным. ИМО, должно быть ключевое слово или подобное в,return
чтобы прояснить это, напримерreturn async result;
(так же, какawait result
"разворачивает"T
изTast<T>
).await
-T foo = someTaskT;
если бы вы получили «Невозможно неявно преобразовать типTask<T>
вT
» - точно так же, как я утверждаю, было бы больше смысла иметь ключевое слово для обратного (обертыванияTask<T>
). Я полностью за удаление мусора, но в данном случае я думаю, что это обеспечивает ненужную обфускацию внутриasync
методов. (Очевидно, это спорный вопрос, потому чтоasync
, думаю, этого достаточно.Не требует преобразования Task в int. Просто используйте результат задачи.
Он вернет значение, если доступно, в противном случае вернет 0.
источник
Result
; это может вызвать взаимоблокировки! Рассмотрим, например, следующий рабочий процесс: (1) Напишите заметку «косить лужайку». (2) Дождитесь, пока газон будет подстрижен (3) Съешьте бутерброд, (4) Делайте все, что написано в записке ". При таком рабочем процессе вы никогда не съедите бутерброд и не косите газон, потому что шаг 2 - это синхронное ожидание. на то, что вы будете делать в будущем . Но это рабочий процесс, который вы описываете здесь.