В чем преимущество запуска асинхронного кода с помощью task.run()

Мне трудно понять преимущества переноса асинхронной работы на Task.Run(). Раньше было много вопросов об асинхронной работе, выгружаемой в задачу, но я никогда не видел, чтобы решалась самая большая загадка для меня.

рассмотреть два варианта:

  • Опция 1:
var t1= Task.Run( async() =>
        {
            await CPUBoundWorkAsync();
        });
  • вариант 2:
var t2= Task.Run( () =>
        {
             CPUBoundWork();
        });

При втором варианте работа выгружается в отдельный поток, таким образом «достигается» асинхронность, и основной поток может вернуться к тому, для чего он нужен. При первом варианте используется асинхронный метод, а делегат выражается как асинхронный. Оба варианта должны давать неотличимый результат с точки зрения отсутствия блокировки основного потока и одновременного завершения работы, связанной с процессором. Есть ли польза от использования асинхронного метода в Task.Run? мне кажется, что это по сути, позволяя работе, которая уже выполняется асинхронно (в другом неблокирующем потоке), также выполняться асинхронно.. Может ли пул потоков или что-то еще, управляющее этими потоками задач, прочитать это? а затем, возможно, дать этому ожидающему потоку какую-то другую работу? если это так, я не видел упоминания об этом ни в одном блоге эксперта или на соответствующей странице в Интернете.

Являются ли f1 и f2 неизменными между двумя вариантами? Это означает, что в первом варианте вы ожидаете f1до, вызывая f2, тогда как во втором варианте вы вызываете f1, игнорируете возвращаемый объект Task, не (a) ждете его завершения, а затем немедленно вызываете f2, возможно, пока f1 все еще выполняется ?

Lasse V. Karlsen 16.05.2022 21:22

@LasseV.Karlsen, вы правы, отредактировал вопрос.

Ben Guri 16.05.2022 21:34

Ваш вопрос связан с этим? ожидание Task.Run против ожидания

Theodor Zoulias 16.05.2022 21:37

@TheodorZoulias, этот вопрос касается чего-то другого и гораздо более простого

Ben Guri 16.05.2022 21:43

Отвечает ли это на ваш вопрос? ожидание Task.Run против ожидания

MKR 16.05.2022 23:12

@MKR отвечает на другой вопрос

Ben Guri 16.05.2022 23:17

Честно говоря, я не понимаю вопроса. Вы представляете два варианта, которые имеют значение только в меньшинстве случаев, когда синхронный и асинхронный API доступны для одной и той же функциональности (Read/AsyncRead в вашем примере). Но вы не спрашиваете, какой из них лучше, потому что я предполагаю, что вы это уже знаете. Таким образом, вы на самом деле сравниваете не вариант 1 с вариантом 2, а вариант 1 с вариантом 3, не говоря, что такое вариант 3, и подразумевая, что это не естественно var t3 = AsyncRead();. Хотите уточнить?

Theodor Zoulias 16.05.2022 23:39

@TheodorZoulias Стивен Клири понял и отлично ответил на свой ответ ниже. Он указал, что метод возвращается в пул потоков после «ожидания», поэтому поток возвращается и может выполнять другую работу, что является «выгодой» от этого в контексте Task.Run().

Ben Guri 17.05.2022 18:09

@ Бен Стивен Клири, возможно, лучше умеет читать мысли, чем остальные, и понял, что вы действительно хотели знать, из той небольшой информации, которую вы дали в вопросе. Итак, если вы намеревались получить ответ от Стивена, цель достигнута! :-)

Theodor Zoulias 17.05.2022 18:34

@TheodorZoulias, или, возможно, вы мало склонны интерпретировать вопросы таким образом, чтобы это соответствовало вашей зоне комфорта знаний;)

Ben Guri 17.05.2022 18:42

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

Theodor Zoulias 17.05.2022 18:54

@TheodorZoulias Я думаю, что это довольно ясно, и я снова пересмотрел его, чтобы сделать его еще яснее, очевидно, ответ, предоставленный Стивеном, дал на него точный и короткий ответ. вопрос затрагивает важную, но нюансированную деталь, и что простой ответ на него отсутствует во многих источниках, которые я проверил, включая сообщения в блогах экспертов и онлайн-курсы обучения. Я чувствую, что этот вопрос может помочь еще нескольким разработчикам, которые могут наткнуться на асинхронность в контексте Task.Run и быть пронизанными таким же образом.

Ben Guri 17.05.2022 19:06

Мне до сих пор непонятно, потому что я не знаю, что вы хотите с чем сравнить. Если вопрос "зачем мне использовать X, если нет другого выхода", то очевидный ответ — «вы вынуждены использовать Х, потому что другого выхода нет». Пожалуйста, рассмотрите возможность представления осмысленных вариантов, чтобы вопрос был осмысленным.

Theodor Zoulias 17.05.2022 19:13

Кстати, если вы думаете, что, изменив имена методов в вопросе с AsyncRead/Read на CPUBoundWorkAsync/CPUBoundWork, вопрос станет более ясным, по крайней мере, для меня это не так. Название CPUBoundWorkAsync специально создает для меня противоречивые ожидания относительно того, что этот метод может делать внутри. CPUBound-часть означает, что он интенсивно использует по крайней мере один поток, а Async-часть — что он использует нет нити. Мне интересно, что другие люди думают об этом.

Theodor Zoulias 17.05.2022 19:13

@TheodorZoulias, очевидно, я сделал больше, чем просто изменил имена, но делайте, как хотите.

Ben Guri 17.05.2022 19:15
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
Четыре эффективных способа центрирования блочных элементов в CSS
Четыре эффективных способа центрирования блочных элементов в CSS
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то...
0
15
98
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

В вашем примере, если f1() и f2() являются асинхронными (в том смысле, что они возвращают задачу), тогда ключевое слово async позволит вам ожидать тех, кто внутри вашего Task.Run().

Ваш вопрос похож на «почему вы помечаете метод Любые как асинхронный»… потому что вы хотите запускать асинхронный код внутри. Или, точнее, вы хотите, чтобы компилятор построил конечный автомат для обработки «ожидания» завершения асинхронной операции.

Я отредактировал вопрос, очевидно, я не имел в виду, что f1() и f2() возвращаются немедленно

Ben Guri 16.05.2022 21:44

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

Scott Perham 16.05.2022 21:50

Я не уверен, правильно ли я понял ваш вопрос. Ориентируясь на «по сути, это позволяет коду, который уже выполняется асинхронно, также выполняться асинхронно»:

Хотя запуск асинхронного кода внутри Task.Run кажется бессмысленным, бывают ситуации, когда это может быть необходимо. Асинхронные методы всегда выполняются синхронно, пока не произойдет первый «настоящий» асинхронный вызов. Хорошим примером является использование фоновые услуги.

Ответ принят как подходящий

With the 2nd option, the work is already being offloaded to a separate thread, then the asynchronicity is already gained in the scope of the program that invoked t2.

Task.Run не делает что-то асинхронным. Это позволяет вам запускать синхронный код в потоке пула потоков (и, таким образом, блокировать поток пула потоков вместо какого-либо другого потока), но я бы не сказал, что это «делает его асинхронным». Код по-прежнему синхронно блокирует поток.

Now although the work that is being done in the 1st option is declared and implemented as async, it's essentially letting code that is already being ran asynchronously, to also run itself asynchronously. What benefits from it ? Can the the scheduler or whatever manages those task threads read into this? and then perhaps give that awaiting thread some work on another task ?

Тредов нет await. Способы await. Когда поток запускает метод и попадает в await, этот метод приостанавливается, метод возвращается к вызывающей стороне, а поток продолжает выполнение. В случае делегата, переданного Task.Run, await вызовет возврат метода -- в пул потоков, тем самым возвращая поток в пул потоков. Когда задача awaited завершится, поток из пула потоков будет использоваться для возобновления выполнения метода; это может быть тот же поток или совершенно другой поток.

Дополнительная информация о как именно await работает находится в моем блоге.

if this is the case I haven't seen it mentioned in any expert blog post, or relevant page on the internet.

У меня серия на Task.Run этикет. По сути, Task.Run в основном используется для разгрузки синхронной или связанной с процессором работы из потока пользовательского интерфейса в приложениях с графическим интерфейсом. Это также иногда полезно в сценариях на стороне сервера, если вы хотите быстро начать что-то обрабатывать, вернуться назад и взять следующее для обработки. Есть еще несколько вариантов использования, но они редки.

Все эти причины могут относиться к асинхронным API. Иногда API появляться асинхронны, но на самом деле это не так. Или некоторые методы являются асинхронными, но они выполняют нетривиальный объем синхронной работы первый, поэтому в некоторых случаях Task.Run по-прежнему желателен даже с асинхронным кодом.

Привет спасибо. Подробная информация о потоке, возвращающемся в пул потоков, отвечает на вопрос. У меня было ощущение, что это должно быть поведение, но нигде не было указано явно, что я смотрел, возможно, это слишком много нюансов или очевидно для большинства программистов (?)

Ben Guri 17.05.2022 18:05

Другие вопросы по теме