2016-12-09 4 views
6

Я пытаюсь понять async - await на глубоком уровне. Всякий раз, когда я вижу примеры того, как это работает, в примере используется способ await, который можно использовать как LongRunningTask или аналогичный, и в нем Task.Delay или new WebClient().Download("http://google.com") или что-то подобное. Я пытаюсь понять, что будет строгое определение того, что следует ожидать. Это не может быть просто «долговременной задачей», поскольку долговременная задача может быть чем-то вроде поиска максимального подмассива массива размером 1 000 000 000, что не принесло бы никакой пользы от эффективности, если бы это было await ed, если это true, что async - await не создает новые темы.Что такое строгое определение того, что должно быть «ожидаемой» задачей?

Из того, что я понимаю, если у вас есть что-то вроде

var task = LongRunningTask(); 
DoSomething(); 
int x = DoSomethingElse(); 
int y = await task; 
int z = x + y; 

то куска

DoSomething(); 
int x = DoSomethingElse(); 

является то, что вы намекаете на компилятор, который

«Эй, компилятор, если вы можете проверить, что этот кусок не имеет никаких зависимостей от LongRunningTask и вице -верса, тогда вы можете начать , разделив вашу работу между LongRunningTask и этим фрагментом кода. Это вы еще не закончили LongRunningTask к тому времени, как вы закончите этот кусок кода, а затем просто работать на добивании LongRunningTask, поэтому почему я говорю вам await это.»

Можете ли вы помочь выпрямить меня ?

+0

Асинхронных/Await был добавлен в 4.5, чтобы дать программист, которые предназначаются для WinRT (ака UWP, иначе Modern UI , aka Store, aka Phone) шанс для написания правильного кода. У этого есть * очень * строгое определение, все, что может занять более 50 миллисекунд. Вероятно, вы можете быть немного более избирательным, чем * что-либо *, а 50 мсек - довольно драконов, я лично использую 1 секунду как «слишком длинный» предел и, если это разумно, будет бросать курсор песочных часов. Избежать слива маленькой батареи - совсем другое соображение, тогда она становится драконовкой. –

ответ

5

await не так мал, как вы думаете. В вашем примере решение о том, следует ли использовать другие потоки, или процедуры завершения ввода-вывода и т. Д., Не находится в любом кода, который вы указали.

Реализация LongRunningTask, будучи метод, который возвращает уже начал Task, вносил комплексные решения о как и когда что Task будет завершена.

Все, что await is is to wait (как следует из названия) для чего-то, что уже началось.

Теперь еслиLongRunningTask реализуется путем создания новых задач, и эти задачи с помощью планировщика по умолчанию, который использует этот пул потоков, и если ваш текущий метод уже работает на поток пула потоков и некоторого из заданий, созданных LongRunningTask, ожидают появления потока пула потоков, то есть возможно, что тот самый поток, который выполнял ваш код, становится доступным, когда встречается await и будет использоваться для запуска одной из задачи ожидания. Но это в основном то, о чем вам не нужно думать.

1

Для целей вашего вопроса, затянувшаяся задача является любой задачей, которая включает в себя вход/выход (I/O).

Это по преимуществу класс задач, которые могут быть ожидавшими, потому что обычно происходит с I/O, что компьютер выдает inst чтобы начать ввод-вывод, а затем просто ждет (обычно в состоянии с низким процессором) для завершения ввода-вывода.

Таким образом, new WebClient().Download("http://google.com") является хорошим примером задачи, которая включает в себя операции ввода-вывода, поскольку для выполнения этой задачи машине необходимо будет подготовить запрос на google.com, начать отправку его через сокет, дождаться запрос, который должен быть полностью отправлен, затем дождитесь ответа, чтобы начать прибывать, а затем дождитесь, пока ответ полностью не придет.

Однако это определение не является строгим; даже если найти максимальный подмассив массива размером 1,000,000,000 может быть долговременной задачей, если он был реализован путем создания нового потока, потому что, если речь идет о вызывающем потоке, у нас будет очень похожий сценарий: (создайте новый поток, передав ему массив для поиска), а затем дождитесь результатов, ничего не делая.

Редактировать

В свете вышеизложенного, максимальные-подмассив-из-огромного массива примеров можно были бы рассматривать как отвлекающий маневр, так как с целью асинхронного-ОЖИДАНИЯ, вопрос о том это или она не является долговременной задачей, зависит от того, запущена ли она в отдельном потоке или нет.

Таким образом, гораздо более четкое определение продолжительной задачи может быть:

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

Так, например, если вы пишете интерактивное приложение (GUI), и вы хотите, чтобы гарантировать время отклика в 200 миллисекунд для вашего человеческого пользователя, то любая задача, которая неизбежно займет больше времени, чем это долговременная задача: вы запустите ее, ждите ее, и пока она работает, ваш графический интерфейс по-прежнему реагирует. С другой стороны, если вы пишете задание пакетной обработки, которое предназначено для работы в одночасье, чтобы хрустить некоторые большие данные, тогда практически никакая задача не стоит рассматривать как долговременную задачу.

+0

Использует ли 'Task.Delay' ввод/вывод? – user7127000

+0

Нет, это не так.Он просто устанавливает таймер, который будет срабатывать позже, а затем он сразу же возвращается. Когда таймер срабатывает, ожидание завершается. Но они используют его только в примерах как ** placeholder ** для реальной долговременной задачи. –

0

Как указано в приведенном выше ответе, Задача МОЖЕТ запускать разные потоки и ждать результата для этих конкретных задач.

Обычно задачи, такие как вызовы API, которые полностью не зависят от мощности обработки, т. Е. Даже если у вас есть максимальная ОЗУ, процессор не имеет или мало влияет на ваш ответ, т. Е. Время задержки ввода-вывода, которое необходимо выполнить , И те задачи, которые внутренне завершены рабочий поток и, как правило, должны быть ожидали

Ссылки: Essential C# 6,0 (5th Edition)

+2

1) Если вы хотите ссылаться на другой ответ, обычно лучше включить ссылку на него, а не использовать позиционную формулировку (например, «выше»), так как ответы могут быть перегруппированы из-за голосования, рандомизации и т. Д. 2) ждут делает * не * запускает потоки. ожидание не * начало * что угодно. await всегда работает с «awaitables», и эти ожидаемые элементы (такие как «Задачи») представляют собой работу, которая * уже * была запущена чем-то другим. –

+0

Да - важное различие здесь заключается в том, что 'await' не знает или не заботится о том, использует ли основной процесс нити или нет; он просто заботится о том, чтобы теперь он возвращал неполную задачу и продолжал позже. * Вообще говоря * (т. Е. В большинстве случаев использования), вероятно, нет потока, но это просто потому, что основной вариант использования - это, по сути, асинхронные задачи, такие как выполнение HTTP-запросов. –

 Смежные вопросы

  • Нет связанных вопросов^_^