S>>>> В JavaScript, под влиянием TypeScript пришли к тому, что await значительно лучше чем создание цепочек обратных вызовов S>>·>Лучше, конечно. Но речь идёт про virtual threads. С ними не нужен ни await, ни цепочки обратных вызовов. Можно писать тупой синхронный код и выполнять на миллионах тредов. S>> Речь вообще то идет про асинхронный код в общем. virtual threads не покрывает все возможные варианты. Я специально тебе вопросы задавал. ·>А ответы-то прочитал?
Потому, что task это задача. А задачу я могу использовать множествами способов. Начиная от await но и Task.WhenAll и WhenEny а так же создавать задачи на основе TaskCompletionSource.
А так же использовать CancellationToken
На самом деле внутри await выполняется множество дочерних задач и нужно их контролировать если не выполнилась одна из родительских задач.
Даже обычное асинхронное может использовать таймауты, которое внутри использует WhenEny.
И вот вопрос как отличать Task как асинхронное и параллельное использование?
В той же Java используются FutureTask. Callable и Future
Казалось бы зачем?
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, ·, Вы писали:
·>Здравствуйте, Serginio1, Вы писали:
S>>>> В JavaScript, под влиянием TypeScript пришли к тому, что await значительно лучше чем создание цепочек обратных вызовов S>>·>Лучше, конечно. Но речь идёт про virtual threads. С ними не нужен ни await, ни цепочки обратных вызовов. Можно писать тупой синхронный код и выполнять на миллионах тредов. S>> Речь вообще то идет про асинхронный код в общем. virtual threads не покрывает все возможные варианты. Я специально тебе вопросы задавал. ·>А ответы-то прочитал?
S>>virtual threads хороши для переноса синхронного кода. Но когда мне нужно параллельно запустить несколько задач , скачать с нескольких ресурсов и продолжить после завершения всех скачанных или первого скачанного, то как мне помогут virtual threads? ·>Ты, похоже, не понимаешь разницу между асинхронным и параллельным исполнением. Это ортогональные понятия. ·>Ты напишешь обычный синхронный код, который это всё сделает. В этом топике уже несколько раз пережевывалось, перечитай. ·>Например, для первого скачанного будет как-то так: ·>
·>В случае шарпа тебе придётся завести пары методов downloadSomeData/downloadSomeDataAsync, download/downloadAsync и кучу копипасты.
Зачем? Еще раз для асинхронных методов достаточно downloadSomeDataAsync и вызов через await Task.WhenAll ·>Давай ещё с другой стороны попробую зайти. Вот тут ты написал: S>>var res = await task; // или в синхронном варианте int res = task.Result; ·>Вот зачем этот выбор? Более того, если ты воткнёшь тут "await", это значит сам метод придётся объявить async. И, возможно, это будет интерфейсный метод, тогда все его имплементации тоже придётся переделывать в async (даже если они простые и без всякой многопоточки/io). И все места вызовов этого метода. И где-то выше по стеку придётся ещё воткнуть await.
Еще раз. витруальные потоки хороши для асинхронизации синхронного кода. Всё!
·>Зачем это всё?! Почему нельзя просто всегда писать "int res = task.Result"? ·>Сабж?
Затем, что мы останавливаем и поток для дожидания результата. Ведь он может выполняться значительно дольше чем код кода до task.Result.
task.Result это для поддержки старого синхронного кода. Вот где преимущество виртуальных потоков.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Serginio1, Вы писали:
S> Потому, что task это задача. А задачу я могу использовать множествами способов. Начиная от await но и Task.WhenAll и WhenEny а так же создавать задачи на основе TaskCompletionSource. S>А так же использовать CancellationToken
CancellationToken вообще не нужен. Закрытие scope отменит все незавершенные задачи сам. Об этом я уже тебе писал.
S>На самом деле внутри await выполняется множество дочерних задач и нужно их контролировать если не выполнилась одна из родительских задач.
И что? Ты вообще читаешь что тебе пишут? И на вопросы ответь.
S> Даже обычное асинхронное может использовать таймауты, которое внутри использует WhenEny.
Мой же пример с таймаутом изменится вот так:
try (var scope = StructuredTaskScope.open(Joiner.<Data>anySuccessfulOrThrow(),
cf -> cf.withTimeout(ofMinutes(5)) // вот это добавить
))
И собственно всё.
S> И вот вопрос как отличать Task как асинхронное и параллельное использование?
Суть вопроса не понял.
S> В той же Java используются FutureTask. Callable и Future S>Казалось бы зачем?
Не обязательно. В моём примере выше — не используются. Ещё раз: Это ортогональные понятия.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, Serginio1, Вы писали:
S> Зачем? Еще раз для асинхронных методов достаточно downloadSomeDataAsync
А почему ты решил, что downloadSomeData — асинхронный метод, притом всегда? Вдруг он что-то просто из памяти достаёт в большинстве случаев?
S> и вызов через await Task.WhenAll
Это значит, что метод содержащий await Task.WhenAll тоже обязан быть async. Зачем??!
S>>>var res = await task; // или в синхронном варианте int res = task.Result; S>·>Вот зачем этот выбор? Более того, если ты воткнёшь тут "await", это значит сам метод придётся объявить async. И, возможно, это будет интерфейсный метод, тогда все его имплементации тоже придётся переделывать в async (даже если они простые и без всякой многопоточки/io). И все места вызовов этого метода. И где-то выше по стеку придётся ещё воткнуть await. S> Еще раз. витруальные потоки хороши для асинхронизации синхронного кода. Всё!
Неверно. Для параллельного исполнения, а не асинхронизации. Потоки в принципе для этого и придумывали.
S>·>Зачем это всё?! Почему нельзя просто всегда писать "int res = task.Result"? S>·>Сабж? S> Затем, что мы останавливаем и поток для дожидания результата. Ведь он может выполняться значительно дольше чем код кода до task.Result. S>task.Result это для поддержки старого синхронного кода. Вот где преимущество виртуальных потоков.
Так что же плохого в старом синхронном коде при наличии виртуальных потоков? А хорошее, очевидно, есть. Синхронный код проще.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, Serginio1, Вы писали:
Gt_>>тебе же вежливо разжували, зачем дурачком прикидываться ? virtual threads помогут написать сам метод, не задумываясь о параллельности. большая разница на фоне .net, где нужно четко понимать что метод будет частью асинхронного кода и нужно очень внимательно следить, что бы не застопорить всю параллельность на какой-нить и/о ожидании. S> Gt_ не читатель. Еще раз. virtual threads хороши для переноса синхронного кода. Всё! S>А вот когда нам нужна параллельность они ну никак в Красную Гвардию не годятся.
Так тебе пишут про синхронный параллельный код.
S> Что касается .Net то помню в Windows Mobile были только асинхронные методы. Большинство используют асинхронные методы. Проблем с async/await ни у кого нет.
И как дела у этого твоего Windows Mobile? Где можно свеженькую версию скачать?
S>Что касается неправильного вызова, то есть варнинги и ошибки при компиляции.
Круто, конечно. А ещё можно в гамаке и в противогазе код писать.
S>Кстати а как virtual threads существуют с FutureTask?
На этот вопрос уже несколько раз отвечали.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
S>> И вот вопрос как отличать Task как асинхронное и параллельное использование? ·>Суть вопроса не понял.
Суть в том что я могу вызвать метод как с await так и без await не дожидаясь результата
S>> В той же Java используются FutureTask. Callable и Future S>>Казалось бы зачем? ·>Не обязательно. В моём примере выше — не используются. Ещё раз: Это ортогональные понятия.
Тогда зачем они нужны?
Опять же мы говорим как об асинхронном и паралельном программировании. В C# это сделано единообразно через Task.
В Java там целый зоопарк при этом еще и кучей багов Structured Concurrency в Java: наконец-то находит опору
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, ·, Вы писали:
·>Здравствуйте, Serginio1, Вы писали:
S>> Зачем? Еще раз для асинхронных методов достаточно downloadSomeDataAsync ·>А почему ты решил, что downloadSomeData — асинхронный метод, притом всегда? Вдруг он что-то просто из памяти достаёт в большинстве случаев?
Ты сам что то придумал и объясняешь.
S>> и вызов через await Task.WhenAll ·>Это значит, что метод содержащий await Task.WhenAll тоже обязан быть async. Зачем??!
Затем, что это асинхронный метод. Для синхронных есть Task.WaitAll. Task можно создавать с опцией LongRunning
S>>>>var res = await task; // или в синхронном варианте int res = task.Result; S>>·>Вот зачем этот выбор? Более того, если ты воткнёшь тут "await", это значит сам метод придётся объявить async. И, возможно, это будет интерфейсный метод, тогда все его имплементации тоже придётся переделывать в async (даже если они простые и без всякой многопоточки/io). И все места вызовов этого метода. И где-то выше по стеку придётся ещё воткнуть await. S>> Еще раз. витруальные потоки хороши для асинхронизации синхронного кода. Всё! ·>Неверно. Для параллельного исполнения, а не асинхронизации. Потоки в принципе для этого и придумывали.
Изначально асинхронность была придумана для асинхронного ввода вывода когда реальные потоки не используются.
S>>·>Зачем это всё?! Почему нельзя просто всегда писать "int res = task.Result"? S>>·>Сабж? S>> Затем, что мы останавливаем и поток для дожидания результата. Ведь он может выполняться значительно дольше чем код кода до task.Result. S>>task.Result это для поддержки старого синхронного кода. Вот где преимущество виртуальных потоков. ·>Так что же плохого в старом синхронном коде при наличии виртуальных потоков? А хорошее, очевидно, есть. Синхронный код проще.
Ты не читатель. Я как раз и говорю, что виртуальные потоки хороши для старого синхронного кода.
Но для нового кода сложно использовать виртуальные потоки и Task так как задачи используются не только для асинхронного, но и параллельного кода.
То есть код надо переделывать на async/await.
По мне так C# значительно лучше Java.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Serginio1, Вы писали:
S>>> И вот вопрос как отличать Task как асинхронное и параллельное использование? S>·>Суть вопроса не понял. S>Суть в том что я могу вызвать метод как с await так и без await не дожидаясь результата
Допустим. Вопрос-то в чём? Что тебе надо отличать и с какой целью?
S>>> В той же Java используются FutureTask. Callable и Future S>>>Казалось бы зачем? S>·>Не обязательно. В моём примере выше — не используются. Ещё раз: Это ортогональные понятия. S> Тогда зачем они нужны?
Кому нужны? Для чего нужны? Ещё раз: в моём примере параллельного кода они не нужны (но можно, если очень хочется).
S> Опять же мы говорим как об асинхронном и паралельном программировании. В C# это сделано единообразно через Task. S>В Java там целый зоопарк при этом еще и кучей багов
Ты опять послал ссылку, однако, статью прочитать не смог.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, Serginio1, Вы писали:
S>>> и вызов через await Task.WhenAll S>·>Это значит, что метод содержащий await Task.WhenAll тоже обязан быть async. Зачем??! S> Затем, что это асинхронный метод. Для синхронных есть Task.WaitAll. Task можно создавать с опцией LongRunning
_Зачем_ он асинхронный?
S>>> Еще раз. витруальные потоки хороши для асинхронизации синхронного кода. Всё! S>·>Неверно. Для параллельного исполнения, а не асинхронизации. Потоки в принципе для этого и придумывали. S>Изначально асинхронность была придумана для асинхронного ввода вывода когда реальные потоки не используются.
Ок, уже лучше. А _зачем_ нужен асинхронный ввод-вывод? Что плохого в коде, который делает просто что-то вроде print(file.read(...)) или sendResults(sqlQuery.execute(...))?
S>>> Затем, что мы останавливаем и поток для дожидания результата. Ведь он может выполняться значительно дольше чем код кода до task.Result. S>>>task.Result это для поддержки старого синхронного кода. Вот где преимущество виртуальных потоков. S>·>Так что же плохого в старом синхронном коде при наличии виртуальных потоков? А хорошее, очевидно, есть. Синхронный код проще. S> Ты не читатель. Я как раз и говорю, что виртуальные потоки хороши для старого синхронного кода.
С этим я и не спорю. И это офигенное преимущество — берём старый код и запускаем параллельно ничего не стесняясь.
S>Но для нового кода сложно использовать виртуальные потоки и Task так как задачи используются не только для асинхронного, но и параллельного кода.
А вот с этим спорю. В чём сложность-то?
S>То есть код надо переделывать на async/await.
Зачем надо?
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
S>>>> И вот вопрос как отличать Task как асинхронное и параллельное использование? S>>·>Суть вопроса не понял. S>>Суть в том что я могу вызвать метод как с await так и без await не дожидаясь результата ·>Допустим. Вопрос-то в чём? Что тебе надо отличать и с какой целью?
Вопрос в том как отличить дожидаться задачи или не надо? S>>>> В той же Java используются FutureTask. Callable и Future S>>>>Казалось бы зачем? S>>·>Не обязательно. В моём примере выше — не используются. Ещё раз: Это ортогональные понятия. S>> Тогда зачем они нужны? ·>Кому нужны? Для чего нужны? Ещё раз: в моём примере параллельного кода они не нужны (но можно, если очень хочется).
Раз они есть значит нужны. В примере FutureTask. Callable и Future выполняются паралельно с текущим кодом и затем дожидаются результата.
S>> Опять же мы говорим как об асинхронном и паралельном программировании. В C# это сделано единообразно через Task. S>>В Java там целый зоопарк при этом еще и кучей багов ·>Ты опять послал ссылку, однако, статью прочитать не смог.
То есть ты утверждаещшь, что в Ява нет зоопарка и проблем со API structured concurrenc
и солнце б утром не вставало, когда бы не было меня
S>>>> и вызов через await Task.WhenAll S>>·>Это значит, что метод содержащий await Task.WhenAll тоже обязан быть async. Зачем??! S>> Затем, что это асинхронный метод. Для синхронных есть Task.WaitAll. Task можно создавать с опцией LongRunning ·>_Зачем_ он асинхронный?
Затем что задача выполняется в отдельном потоке.
S>>>> Еще раз. витруальные потоки хороши для асинхронизации синхронного кода. Всё! S>>·>Неверно. Для параллельного исполнения, а не асинхронизации. Потоки в принципе для этого и придумывали. S>>Изначально асинхронность была придумана для асинхронного ввода вывода когда реальные потоки не используются. ·>Ок, уже лучше. А _зачем_ нужен асинхронный ввод-вывод? Что плохого в коде, который делает просто что-то вроде print(file.read(...)) или sendResults(sqlQuery.execute(...))?
Да ничего. Просто при print задействован контроллер, а не CPU. Операционная система — аппаратное обеспечение ввода-вывода
S>>>> Затем, что мы останавливаем и поток для дожидания результата. Ведь он может выполняться значительно дольше чем код кода до task.Result. S>>>>task.Result это для поддержки старого синхронного кода. Вот где преимущество виртуальных потоков. S>>·>Так что же плохого в старом синхронном коде при наличии виртуальных потоков? А хорошее, очевидно, есть. Синхронный код проще. S>> Ты не читатель. Я как раз и говорю, что виртуальные потоки хороши для старого синхронного кода. ·>С этим я и не спорю. И это офигенное преимущество — берём старый код и запускаем параллельно ничего не стесняясь.
С этим никто не спорит. Об этом я тебе сразу и писал. Проблема в поддержке старого и нового.
Так как Task отвечает не только за асинхронность, но и параллельность.
S>>Но для нового кода сложно использовать виртуальные потоки и Task так как задачи используются не только для асинхронного, но и параллельного кода. ·>А вот с этим спорю. В чём сложность-то?
Ну ты сам приводил кучу когда, где использовались различные апи.
S>>То есть код надо переделывать на async/await. ·>Зачем надо?
Ну вот как с тобой разговаривать? Прочитай еще раз внимательно
Так как Task отвечает не только за асинхронность, но и параллельность.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Serginio1, Вы писали:
S>·>Допустим. Вопрос-то в чём? Что тебе надо отличать и с какой целью? S>Вопрос в том как отличить дожидаться задачи или не надо?
Это вопрос бизнес-требований. Но, как правило, дожидаться надо всегда.
Напомню. Мы сравниваем вот такой код: var res = await task; // или в синхронном варианте int res = task.Result;
В обоих случаях код дожидается завершения задачи.
S>>>>> В той же Java используются FutureTask. Callable и Future S>>>>>Казалось бы зачем? S>>>·>Не обязательно. В моём примере выше — не используются. Ещё раз: Это ортогональные понятия. S>>> Тогда зачем они нужны? S>·>Кому нужны? Для чего нужны? Ещё раз: в моём примере параллельного кода они не нужны (но можно, если очень хочется). S> Раз они есть значит нужны.
Нет, не значит. Future появилось в java версии 1.5 (это 2004 год). А виртуальные потоки в версии 21 (это 2023 год).
S> В примере FutureTask. Callable и Future выполняются паралельно с текущим кодом и затем дожидаются результата.
И?
S>·>Ты опять послал ссылку, однако, статью прочитать не смог. S> То есть ты утверждаещшь, что в Ява нет зоопарка и проблем со API structured concurrenc
Единственная проблема на сегодняшний день — оно preview. Но это не мешает писать простой синхронный код.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
S>>·>Допустим. Вопрос-то в чём? Что тебе надо отличать и с какой целью? S>>Вопрос в том как отличить дожидаться задачи или не надо? ·>Это вопрос бизнес-требований. Но, как правило, дожидаться надо всегда.
·>Напомню. Мы сравниваем вот такой код: var res = await task; // или в синхронном варианте int res = task.Result; ·>В обоих случаях код дожидается завершения задачи.
Я не знаю, что ты там сравниваешь, я просто привел пример использования Task для асинхронного и синхронного кода S>>>>>> В той же Java используются FutureTask. Callable и Future S>>>>>>Казалось бы зачем? S>>>>·>Не обязательно. В моём примере выше — не используются. Ещё раз: Это ортогональные понятия. S>>>> Тогда зачем они нужны? S>>·>Кому нужны? Для чего нужны? Ещё раз: в моём примере параллельного кода они не нужны (но можно, если очень хочется). S>> Раз они есть значит нужны. ·>Нет, не значит. Future появилось в java версии 1.5 (это 2004 год). А виртуальные потоки в версии 21 (это 2023 год).
Ну то есть зоопарк. S>> В примере FutureTask. Callable и Future выполняются паралельно с текущим кодом и затем дожидаются результата. ·>И?
S>>·>Ты опять послал ссылку, однако, статью прочитать не смог. S>> То есть ты утверждаещшь, что в Ява нет зоопарка и проблем со API structured concurrenc ·>Единственная проблема на сегодняшний день — оно preview. Но это не мешает писать простой синхронный код.
Ну вот оказывается еще и preview. При этом никакого преимущества перед async/await практически нет.
async/await более универсальный вариант с использованием Task.WhenAny, Task.WhenAll, TaskCompletionSource, CancellationToken.
При этом давно уже не Preview, а совершенствуется скорость и используемая память.
Если виртуальные потоки хороши для синхронного кода, то на C# его уже не используют для асинхронных методов
В 2012 году с выходом C# 5.0 в языке программирования C# появились ключевые слова async и await для асинхронного программирования.
Была проблема с поддержкой Windows XP. Там нужен был четвертый фреймворк.
Кстати уже с существующем ИИ помошниками, можно легко отрефакторить через Roslyn старый код для использования async/await если у метода есть двойник с суффиксом Async
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Serginio1, Вы писали:
S>·>_Зачем_ он асинхронный? S> Затем что задача выполняется в отдельном потоке.
Выполнение в отдельном потоке означает параллельное выполнение. Это не отвечает на вопрос _зачем_ метод обязан быть асинхронным.
S>·>Ок, уже лучше. А _зачем_ нужен асинхронный ввод-вывод? Что плохого в коде, который делает просто что-то вроде print(file.read(...)) или sendResults(sqlQuery.execute(...))? S> Да ничего.
Именно. Так зачем переписывать "старый код"? Зачем писать новый код с async/await?
S> Просто при print задействован контроллер, а не CPU. S>Операционная система — аппаратное обеспечение ввода-вывода
Речь о коде на языке программирования идёт, а не об операционной системе.
S>>> Ты не читатель. Я как раз и говорю, что виртуальные потоки хороши для старого синхронного кода. S>·>С этим я и не спорю. И это офигенное преимущество — берём старый код и запускаем параллельно ничего не стесняясь. S>С этим никто не спорит. Об этом я тебе сразу и писал. Проблема в поддержке старого и нового. S>Так как Task отвечает не только за асинхронность, но и параллельность.
_Зачем_ он отвечает за параллельность?
S>>>Но для нового кода сложно использовать виртуальные потоки и Task так как задачи используются не только для асинхронного, но и параллельного кода. S>·>А вот с этим спорю. В чём сложность-то? S> Ну ты сам приводил кучу когда, где использовались различные апи.
Э.. И? Выбор api зависит от решаемой задачи. Какой тебе удобно, такой и используй. У тебя есть выбор. Можешь хоть свой API написать. А в случае когда виртуальных потоков нет, приходится устраивать цирк, что ты там нам показывал со всякими асинхронными очередями. Который с треском навернётся, если где-то кто-то как-то внезапно заблокирует что-нибудь.
Или для тебя сложностью является наличие выбора?
S>>>То есть код надо переделывать на async/await. S>·>Зачем надо? S> Ну вот как с тобой разговаривать? Прочитай еще раз внимательно S>
S>Так как Task отвечает не только за асинхронность, но и параллельность.
Нет, за параллельность отвечают потоки. Создаёшь много потоков — они выполяются параллельно. То что тебе _приходится_ использовать асинхронность — это недостаток платформенных тредов. Ты их не можешь запускать миллионами, поэтому _приходится_ переписывать "старый" код. Иначе всё просто падает нахрен.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, Serginio1, Вы писали:
S>·>Напомню. Мы сравниваем вот такой код: var res = await task; // или в синхронном варианте int res = task.Result; S>·>В обоих случаях код дожидается завершения задачи. S> Я не знаю, что ты там сравниваешь, я просто привел пример использования Task для асинхронного и синхронного кода
Ты задал вопрос: "как отличать Task как асинхронное и параллельное использование?". Я попросил уточнить: "с какой целью отличать?". Так зачем их отличать?
S>>>·>Ты опять послал ссылку, однако, статью прочитать не смог. S>>> То есть ты утверждаещшь, что в Ява нет зоопарка и проблем со API structured concurrenc S>·>Единственная проблема на сегодняшний день — оно preview. Но это не мешает писать простой синхронный код. S> Ну вот оказывается еще и preview. При этом никакого преимущества перед async/await практически нет.
Преимущества есть. В статье на которую ты сослался об этом написано.
S>async/await более универсальный вариант с использованием Task.WhenAny, Task.WhenAll, TaskCompletionSource, CancellationToken. S>При этом давно уже не Preview,
Ещё раз. Это WhenAny говно в java уже есть очень давно. Но говном быть не перестаёт, т.к. усложняет код.
S>а совершенствуется скорость и используемая память.
Виртуальные потоки как раз и совершенствуют скорость и память. structured concurrency — это просто небольшая библиотечка для написания простого параллельного кода. Наличие виртуальных потоков позволяет запускать простой код на больших масштабах, неважно какой именно api ты решишь использовать. Например, тупо пишешь в синхронном варианте int res = task.Result; и ни о чём не паришься.
S> Если виртуальные потоки хороши для синхронного кода, то на C# его уже не используют для асинхронных методов
Потому что не могут. Синхронный код в c# не масштабируется.
S>Кстати уже с существующем ИИ помошниками, можно легко отрефакторить через Roslyn старый код для использования async/await если у метода есть двойник с суффиксом Async
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
S>>·>_Зачем_ он асинхронный? S>> Затем что задача выполняется в отдельном потоке. ·>Выполнение в отдельном потоке означает параллельное выполнение. Это не отвечает на вопрос _зачем_ метод обязан быть асинхронным.
Задача может выполняться как в отдельном потоке LongRunning, так и пуле потоков. А там можно настроить, что бы пул потока состоял из одного потока.
Кроме того операции ввода вывода используют один поток использую один поток для контроля выполнения через контроллер.
S>>·>Ок, уже лучше. А _зачем_ нужен асинхронный ввод-вывод? Что плохого в коде, который делает просто что-то вроде print(file.read(...)) или sendResults(sqlQuery.execute(...))? S>> Да ничего. ·>Именно. Так зачем переписывать "старый код"? Зачем писать новый код с async/await?
S>> Просто при print задействован контроллер, а не CPU. S>>Операционная система — аппаратное обеспечение ввода-вывода ·>Речь о коде на языке программирования идёт, а не об операционной системе.
Мы говорим об асинхронных методах, которые используют операции ввода вывода. Ты же спрашиваешь зачем использовать асинхронный код.
S>>>> Ты не читатель. Я как раз и говорю, что виртуальные потоки хороши для старого синхронного кода. S>>·>С этим я и не спорю. И это офигенное преимущество — берём старый код и запускаем параллельно ничего не стесняясь. S>>С этим никто не спорит. Об этом я тебе сразу и писал. Проблема в поддержке старого и нового. S>>Так как Task отвечает не только за асинхронность, но и параллельность. ·>_Зачем_ он отвечает за параллельность?
Затем, что Task работает как с потоками так и пулом потоков со своим планировщиком. Так же компилятор создает класс энумератор со state machine с вызовом MoveNext после выполнения await
S>>>>Но для нового кода сложно использовать виртуальные потоки и Task так как задачи используются не только для асинхронного, но и параллельного кода. S>>·>А вот с этим спорю. В чём сложность-то? S>> Ну ты сам приводил кучу когда, где использовались различные апи. ·>Э.. И? Выбор api зависит от решаемой задачи. Какой тебе удобно, такой и используй. У тебя есть выбор. Можешь хоть свой API написать. А в случае когда виртуальных потоков нет, приходится устраивать цирк, что ты там нам показывал со всякими асинхронными очередями. Который с треском навернётся, если где-то кто-то как-то внезапно заблокирует что-нибудь. ·>Или для тебя сложностью является наличие выбора?
Вот именно, что апи зависит от задач. Task универсален и легко читаем.
S>>>>То есть код надо переделывать на async/await. S>>·>Зачем надо? S>> Ну вот как с тобой разговаривать? Прочитай еще раз внимательно S>>
S>>Так как Task отвечает не только за асинхронность, но и параллельность.
·>Нет, за параллельность отвечают потоки. Создаёшь много потоков — они выполяются параллельно. То что тебе _приходится_ использовать асинхронность — это недостаток платформенных тредов. Ты их не можешь запускать миллионами, поэтому _приходится_ переписывать "старый" код. Иначе всё просто падает нахрен.
Task это задача. Она отвязана от потоков. Еще раз внимательно читаем про операции ввода вывода, TaskCompletionSource
Что там внутри происходит зависит от планировщика, пула потоков, опций для Task.
Задачи работают через пул потоков или поток ввода вывода или при использовании LongRunning используется отдельный поток.
Как это работает на низком уровне
Приложение запрашивает I/O (например, чтение файла).
Диспетчер I/O создает IRP и буфер системной памяти (SystemBuffer).
Диспетчер отправляет IRP соответствующему драйверу устройства (например, драйверу диска).
Драйвер выполняет операцию с устройством, записывая данные в SystemBuffer (для чтения).
Драйвер завершает IRP, вызывая IoCompleteRequest.
Когда поток готов, Диспетчер I/O копирует данные из SystemBuffer в буфер пользователя (для чтения) и освобождает системный буфер, возобновляя работу потока.
и солнце б утром не вставало, когда бы не было меня
S>>·>Напомню. Мы сравниваем вот такой код: var res = await task; // или в синхронном варианте int res = task.Result; S>>·>В обоих случаях код дожидается завершения задачи. S>> Я не знаю, что ты там сравниваешь, я просто привел пример использования Task для асинхронного и синхронного кода ·>Ты задал вопрос: "как отличать Task как асинхронное и параллельное использование?". Я попросил уточнить: "с какой целью отличать?". Так зачем их отличать?
Вот у тебя есть метод
File.WriteAllBytesAsync("file1");
Я могу его вызвать
как
File.WriteAllBytesAsync("file1");
Не дожидаясь результата записи
так и
await File.WriteAllBytesAsync("file1");
S>>async/await более универсальный вариант с использованием Task.WhenAny, Task.WhenAll, TaskCompletionSource, CancellationToken. S>>При этом давно уже не Preview, ·>Ещё раз. Это WhenAny говно в java уже есть очень давно. Но говном быть не перестаёт, т.к. усложняет код.
Угу WhenAny позволяет получить результат первого выполненого и отменить выполнение еще невыполненных.
Или обработать результат первого выполненного.
В чем говно непонятно. Обработка асинхронных задач по мере их выполнения (C#)
S>>а совершенствуется скорость и используемая память. ·>Виртуальные потоки как раз и совершенствуют скорость и память. structured concurrency — это просто небольшая библиотечка для написания простого параллельного кода. Наличие виртуальных потоков позволяет запускать простой код на больших масштабах, неважно какой именно api ты решишь использовать. Например, тупо пишешь в синхронном варианте int res = task.Result; и ни о чём не паришься.
Еще раз несложно с помощью ИИ написать создание асинхронных методов если в них есть методы с имеющие методы с суффиксом Async
S>> Если виртуальные потоки хороши для синхронного кода, то на C# его уже не используют для асинхронных методов ·>Потому что не могут. Синхронный код в c# не масштабируется.
Еще раз несложно через Roslyn преобразовать код.
S>>Кстати уже с существующем ИИ помошниками, можно легко отрефакторить через Roslyn старый код для использования async/await если у метода есть двойник с суффиксом Async
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Serginio1, Вы писали:
S>·>Выполнение в отдельном потоке означает параллельное выполнение. Это не отвечает на вопрос _зачем_ метод обязан быть асинхронным. S> Задача может выполняться как в отдельном потоке LongRunning, так и пуле потоков. А там можно настроить, что бы пул потока состоял из одного потока. S>Кроме того операции ввода вывода используют один поток использую один поток для контроля выполнения через контроллер.
ЗАЧЕМ?? Ты путаешь средство и цель.
S>·>Речь о коде на языке программирования идёт, а не об операционной системе. S> Мы говорим об асинхронных методах, которые используют операции ввода вывода. Ты же спрашиваешь зачем использовать асинхронный код.
Зачем о них говорить? Почему в коде нельзя использовать синхронные операции ввода-вывода?
S>·>_Зачем_ он отвечает за параллельность? S> Затем, что Task работает как с потоками так и пулом потоков со своим планировщиком. Так же компилятор создает класс энумератор со state machine с вызовом MoveNext после выполнения await
Это средство, а не цель. Мне, как программисту, не надо создавать энумераторы. Мне, как программисту, надо выполнить миллион операций ввода-вывода.
S>·>Или для тебя сложностью является наличие выбора? S>Вот именно, что апи зависит от задач. Task универсален и легко читаем.
Нифига он не легко читаем. Примеры асинхронных очередей и т.п. ты мне тут показывал.
S>·>Нет, за параллельность отвечают потоки. Создаёшь много потоков — они выполяются параллельно. То что тебе _приходится_ использовать асинхронность — это недостаток платформенных тредов. Ты их не можешь запускать миллионами, поэтому _приходится_ переписывать "старый" код. Иначе всё просто падает нахрен. S> Task это задача. Она отвязана от потоков. Еще раз внимательно читаем про операции ввода вывода, TaskCompletionSource S> Что там внутри происходит зависит от планировщика, пула потоков, опций для Task.
Угу. Но зачем? Почему нельзя просто писать обычный код с обычными синхронными операциями?
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, Serginio1, Вы писали:
S>·>Ты задал вопрос: "как отличать Task как асинхронное и параллельное использование?". Я попросил уточнить: "с какой целью отличать?". Так зачем их отличать? S>Вот у тебя есть метод
S>
S>File.WriteAllBytesAsync("file1");
S>
Зачем мне такой метод? Что плохого с File.WriteAllBytes("file1")?
S>Не дожидаясь результата записи
Не надо так делать. Если тебе не важны результаты, то нафиг вообще его вызывать?
S>·>Ещё раз. Это WhenAny говно в java уже есть очень давно. Но говном быть не перестаёт, т.к. усложняет код. S>Угу WhenAny позволяет получить результат первого выполненого и отменить выполнение еще невыполненных. S>Или обработать результат первого выполненного. S> В чем говно непонятно. S>Обработка асинхронных задач по мере их выполнения (C#)
Код сложнее. Сам же несколько сообщений назад согласился.
S> Еще раз несложно с помощью ИИ написать создание асинхронных методов если в них есть методы с имеющие методы с суффиксом Async
Можно. Но зачем, если есть возможно не писать такое гно вообще?
S>·>Потому что не могут. Синхронный код в c# не масштабируется. S> Еще раз несложно через Roslyn преобразовать код.
Сложно. Потребуются виртуальные потоки.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай