В чем разница между возвращением void и возвращением задачи?
при просмотре различных образцов C# Async CTP я вижу некоторые асинхронные функции, которые возвращают void и другие, которые возвращают необщего Task. Я могу понять, почему возвращение Task<MyType> полезно возвращать данные вызывающему при завершении асинхронной операции, но функции, которые я видел, имеют тип возврата Task никогда не возвращает никаких данных. Почему бы не вернуться void?
4 ответов:
ответы SLaks и Killercam хороши; я думал, что просто добавлю немного больше контекста.
ваш первый вопрос по существу о том, какие методы могут быть отмечены
async.метод помечен как
asyncможет возвратитьvoid,TaskилиTask<T>. В чем разница между ними?A
Task<T>возвращение асинхронного метода можно ожидать, и когда задача завершится, он предложит T.A
Taskвозврат асинхронного метода можно ожидать, и когда задача завершится, продолжение задачи планируется запустить.A
voidвозвращение асинхронного метода нельзя ожидать; это метод" огонь и забыть". Он работает асинхронно, и вы не можете сказать, когда это будет сделано. Это более чем немного странно; как говорит Слакс, обычно вы делаете это только при создании асинхронного обработчика событий. Событие срабатывает, обработчик выполняется; никто не собирается "ждать задача, возвращаемая обработчиком событий, потому что обработчики событий не возвращают задачи, и даже если они это сделали, какой код будет использовать задачу для чего-то? Обычно это не пользовательский код, который передает управление обработчику в первую очередь.ваш второй вопрос, в комментарии, по сути, о том, что может быть
awaitЭд:какие методы могут быть
awaitЭд? Может ли метод void-returning бытьawaitЭд?нет, пустота-возвращение метод нельзя ждать. Компилятор переводит
await M()в вызовM().GetAwaiter(), гдеGetAwaiterможет быть метод экземпляра или метода расширения. Ожидаемое значение должно быть таким, для которого вы можете получить ожидающего; ясно, что метод возврата пустоты не создает значение, из которого вы можете получить ожидающего.
Task-возвращаемые методы могут создавать ожидаемые значения. Мы ожидаем, что третьи стороны захотят создать свои собственные реализацииTask-как объекты, которые можно ждать, и вы сможете их дождаться. Однако вам не будет разрешено объявлятьasyncметоды, которые возвращают все, кромеvoid,TaskилиTask<T>.(обновление: мое последнее предложение может быть фальсифицировано будущей версией C#; есть предложение разрешить возвращаемые типы, отличные от типов задач, для асинхронных методов.)
(обновление: упомянутая выше функция сделала это в C# 7.)
в случае, если вызывающий абонент хочет подождать с задачей или добавить продолжение.
на самом деле, единственная причина, чтобы вернуться
voidЕсли вы не может возвращениеTaskпотому что вы пишете обработчик событий.
методы возврата
TaskиTask<T>являются составными-это означает, что вы можетеawaitих внутриasyncметод.
asyncметоды возвратаvoidне являются составными, но они имеют два других важных свойства:
- они могут быть использованы в качестве обработчиков событий.
- они представляют собой асинхронную операцию "верхнего уровня".
второй пункт важен, когда вы имеете дело с контекстом, что поддерживает графа незавершенных асинхронных операций.
ASP.NET контекст является одним из таких контекстов; если вы используете async
Taskметоды, не ожидая их от асинхронногоvoidметод, затем ASP.NET запрос будет выполнен слишком рано.другой контекст-это
AsyncContextя написал для модульного тестирования (доступно здесь) - theAsyncContext.Runметод отслеживает количество выдающихся операций и возвращает, когда оно равно нулю.
тип
Task<T>- Это тип рабочей лошадки параллельной библиотеки задач (TPL), он представляет собой понятие "некоторая работа/задание, которое будет производить результат типаTв будущем". Понятие "работа, которая завершится в будущем, но не вернет результата" представлено неродовым типом задачи.точно как результат типа
Tбудет производиться is и детали реализации конкретной задачи; работа может быть передана в другой процесс на локальной машине, в другой поток и т. д. Задачи TPL обычно распределяются по рабочим потокам из пула потоков в текущем процессе, но эта деталь реализации не является фундаментальной дляTask<T>тип; скорее aTask<T>может представлять любую операцию с высокой задержкой, которая создаетT.на основе вашего комментария выше:
The
awaitвыражение означает "оценить это выражение, чтобы получить объект, представляющий работу, которая будет в будущем произведите результат. Зарегистрируйте оставшуюся часть текущего метода как обратный вызов, связанный с продолжением этой задачи. Как только эта задача будет выполнена и обратный вызов зарегистрирован, тут вернуть управление моему абоненту". Это противопоставляется / в отличие от обычного вызова метода, что означает " помните, что вы делаете, запустите этот метод, пока он не будет полностью завершен, а затем поднимите, где вы остановились, теперь зная результат метод."
Edit: я должен процитировать статью Эрика Липперта в октябре 2011 года в журнале MSDN, поскольку это было большим подспорьем для меня в понимании этого материала в первую очередь.
для нагрузок больше информации и ознакомиться с программой здесь.
Я надеюсь, что это поможет.
Comments