Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / WinForms, .Net Framework Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2 3 4 5 6 7 8 9 10 11   вперед  Ctrl      все
 Зачем нужен await?  [new]
hVostt
Member

Откуда:
Сообщений: 14373
Думаю многие сталкивались с ключевым словом await в языках, применяющих async/await паттерн для асинхронного программирования. Основное ограничение, это использование только в async-функциях, это понятно.

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

Понятно, что наличие ключевого слова await позволяет, допустим, собрать все вызовы в коллекцию и эвейтить её, или даже вообще не эвейтить, а выполнить без ожидания, или вернуть awaitable результат (Task, promise, etc.), но для подобного, более редкого, употребления можно было сделать специальный синтаксис.
31 июл 18, 22:50    [21619579]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
MasterZiv
Member

Откуда: Питер
Сообщений: 34216
hVostt
Думаю многие сталкивались с ключевым словом await в языках, применяющих async/await паттерн для асинхронного программирования. Основное ограничение, это использование только в async-функциях, это понятно.

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

Понятно, что наличие ключевого слова await позволяет, допустим, собрать все вызовы в коллекцию и эвейтить её, или даже вообще не эвейтить, а выполнить без ожидания, или вернуть awaitable результат (Task, promise, etc.), но для подобного, более редкого, употребления можно было сделать специальный синтаксис.


Тебе вообще зачем __асинхронный__ вызов нужен?
Наверное, чтобы он выполнялся параллельно с остальным кодом...
А как оно будет выполняться параллельно, если ты тут же будешь ждать результат асинхнонного вызова?
1 авг 18, 00:05    [21619662]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
hVostt
Member

Откуда:
Сообщений: 14373
MasterZiv
Тебе вообще зачем __асинхронный__ вызов нужен?
Наверное, чтобы он выполнялся параллельно с остальным кодом...
А как оно будет выполняться параллельно, если ты тут же будешь ждать результат асинхнонного вызова?


Похоже, вы очень сильно путаете понятия.
Вот вам ссылка почитать

Вкратце, асинхронный вызов мне нужен, чтобы I/O операции не блокировали рабочий поток из пула. Запуск подобного ожидания в параллельном потоке, это костыль, не решающий проблемы, но позволяющий, например, не блокировать единственный UI поток. В контексте серверных веб-приложений, подобный финт ушами вообще бесмысленнен. А в контексте, например, JavaScript и вовсе невозможен (не будем брать в расчёт не так давно появившиеся Web Workers).

В общем, вернёмся к вопросу. Уточню, откуда ноги растут у вопроса. Проблемы две:

1. избыточность повсеместного ключевого слова await, если есть какое-то подозрение, что код модуля будет исполнять асинхронные методы, он тоже должен быть асинхронным.

2. забыли await, получили проблемы, особенно, если мы не ожидаем результат, а только сам факт асинхронного исполнения (async void).
1 авг 18, 00:27    [21619690]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
LR
Member

Откуда: 8P8C
Сообщений: 2321
hVostt,

ситуации разные бывают, с await больше возможностей для разработчика
        static void Main(string[] args)
        {
            MyMethod();
            Thread.Sleep(3000);
            Console.WriteLine("\r\n\r\nВыполняется какая-то работа...");
            sometask.Wait();
            Console.ReadKey();
        }

        static Task sometask;

        static async void MyMethod()
        {
            sometask = Task.Run(() =>
            {
                using (StreamWriter writer = File.CreateText("gloaming.txt"))
                {
                    writer.WriteLine("Длинное, синее, пахнет ямайским ромом. Что это?");
                }
                Thread.Sleep(5000); // что-то длительное...
                using (StreamReader reader = File.OpenText("gloaming.txt"))
                {
                    Console.WriteLine("\r\n\r\n" + reader.ReadLine());
                }
            });
            // тут нужно дождаться
            await (new WebClient().DownloadStringTaskAsync("http://www.sql.ru/forum/1300144/zachem-nuzhen-await"))
                .ContinueWith(t =>
                {
                    Console.WriteLine(t.Result.Substring(t.Result.IndexOf("ведь компилятор может определить"), 100));
                });
            // а тут не нужно, ну нет такой необходимости, как компилятор это определит?
            (new WebClient().DownloadStringTaskAsync("http://www.sql.ru/forum/1300144/zachem-nuzhen-await"))
                .ContinueWith(t =>
                {
                    using (StreamWriter writer = File.CreateText("noproblem.txt"))
                    {
                        writer.WriteLine(t.Result.Substring(t.Result.IndexOf("2. забыли await, получили проблемы"), 100));
                    }
                });
        }
1 авг 18, 01:51    [21619769]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
WebSharper
Member

Откуда:
Сообщений: 348
Тогда после введения этой особенности получилось бы нарушение обратной совместимости. До нее тот же самый код бы просто запускал метод. А после нее эвейтил бы таску.

Причем в документации бы пришлось писать что var x = y() ведёт себя по разному для методов возвращающих такску и прочие типы
1 авг 18, 06:17    [21619805]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
hVostt
Member

Откуда:
Сообщений: 14373
LR
            // тут нужно дождаться
            await (new WebClient().DownloadStringTaskAsync("http://www.sql.ru/forum/1300144/zachem-nuzhen-await"))
                .ContinueWith(t =>
                {
                    Console.WriteLine(t.Result.Substring(t.Result.IndexOf("ведь компилятор может определить"), 100));
                });


Это очень странный код, поясните, зачем вы используете здесь ContinueWith вместе с await?

            // тут нужно дождаться
            var result = await (new WebClient().DownloadStringTaskAsync("http://www.sql.ru/forum/1300144/zachem-nuzhen-await"));
            Console.WriteLine(t.Result.Substring(t.Result.IndexOf("ведь компилятор может определить"), 100));


По поводу второго "не нужно". Это распространённая ошибка. Если приложение нормально завершит свою работу раньше, чем ваш Task, то работа может быть прервана на середине и код в ContinueWith вообще не выполнится. И без await контекст синхронизации нужно передавать вручную (актуально для UI и для ASP.NET, но не Core).
1 авг 18, 08:35    [21619896]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
hVostt
Member

Откуда:
Сообщений: 14373
WebSharper
Тогда после введения этой особенности получилось бы нарушение обратной совместимости. До нее тот же самый код бы просто запускал метод. А после нее эвейтил бы таску.


Т.е. кроме обратной совместимости, других проблем вы не видите?
Думаете, если бы язык проектировался заново, типа новая супер-мажорная версия, без обратной совместимости, от ключевого слова await могли бы отказаться?

WebSharper
Причем в документации бы пришлось писать что var x = y() ведёт себя по разному для методов возвращающих такску и прочие типы


Если бы async был частью контракта, а не реализации, то компилятор бы скрывал таску, y() при этом возвращал результат функции, а не awaitable объект в контексте использования. Проблема в том, что возвращаемый результат типа Task ещё не говорит о том, что это асинхронный метод.
1 авг 18, 08:41    [21619914]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
OoCc
Member

Откуда: с Кавказа
Сообщений: 1488
MasterZiv
hVostt
Думаю многие сталкивались с ключевым словом await в языках, применяющих async/await паттерн для асинхронного программирования. Основное ограничение, это использование только в async-функциях, это понятно.

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

Понятно, что наличие ключевого слова await позволяет, допустим, собрать все вызовы в коллекцию и эвейтить её, или даже вообще не эвейтить, а выполнить без ожидания, или вернуть awaitable результат (Task, promise, etc.), но для подобного, более редкого, употребления можно было сделать специальный синтаксис.


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

+1
1 авг 18, 09:27    [21620006]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
LR
Member

Откуда: 8P8C
Сообщений: 2321
hVostt
По поводу второго "не нужно". Это распространённая ошибка. Если приложение нормально завершит свою работу раньше, чем ваш Task, то работа может быть прервана на середине и код в ContinueWith вообще не выполнится. И без await контекст синхронизации нужно передавать вручную (актуально для UI и для ASP.NET, но не Core).

Это не ошибка, так задумано, если задание не выполнится до окончания работы приложения - это нормально, иначе задумано с sometask. Повторю, ситуации могут быть разными, await дает еще одну степень свободы - и это хорошо.
1 авг 18, 09:28    [21620014]     Ответить | Цитировать Сообщить модератору
 Re: Зачем нужен await?  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 3179
hVostt
Вопрос такой. Почему бы вообще не отказаться от этого ключевого слова и необходимости его употребления, ведь компилятор может определить наличие вызова асинхронного метода и сам выполнить его асинхронно?

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

hVostt
Понятно, что наличие ключевого слова await позволяет, допустим, собрать все вызовы в коллекцию и эвейтить её, или даже вообще не эвейтить, а выполнить без ожидания, или вернуть awaitable результат (Task, promise, etc.), но для подобного, более редкого, употребления можно было сделать специальный синтаксис.

а как тогда должен себя вести код генерируемый компилятором?
  • всегда ждать завершения? тогда 21619662 вполне уместен
  • запоминать что переменная не переменная и её нужно проверять? тогда встаёт вопрос эффективности, фактически придётся делать ленивый вызов при использовании переменной, следить за ней, что в массовом порядке накладно.
  • 1 авг 18, 10:01    [21620111]     Ответить | Цитировать Сообщить модератору
     Re: Зачем нужен await?  [new]
    WebSharper
    Member

    Откуда:
    Сообщений: 348
    hVostt
    Т.е. кроме обратной совместимости, других проблем вы не видите?
    Думаете, если бы язык проектировался заново, типа новая супер-мажорная версия, без обратной совместимости, от ключевого слова await могли бы отказаться?


    При этом можно было бы ввести другое умолчание (соответственно для поведения когда мы продолжаем исполнение, а не возвращаем управление вызвавшему методу).
    Т.е. у нас есть 3 действия - получить таску и что-то с ней сделать. Вернуть управление вызвавшему методу. Подождать пока вызванный метод закончится. Нам их надо как-то разграничить.
    1 авг 18, 12:49    [21620890]     Ответить | Цитировать Сообщить модератору
     Re: Зачем нужен await?  [new]
    hVostt
    Member

    Откуда:
    Сообщений: 14373
    LR
    Это не ошибка, так задумано, если задание не выполнится до окончания работы приложения - это нормально, иначе задумано с sometask. Повторю, ситуации могут быть разными, await дает еще одну степень свободы - и это хорошо.


    Спорить не буду. Лично я считаю, что запуск задач по принципу fire and forget должен осуществляться через планировщик заданий, и нормальное завершение программы не должно осуществляться путём terminate запущенных потоков. Либо нужно дожидаться выполнения всех заданий, либо посылать сигнал с требованием немедленного завершения работ, как минимум через CancellationToken, если мы говорим про C#.

    Так что это выглядит как ошибка и никак иначе.

    LR
    Повторю, ситуации могут быть разными, await дает еще одну степень свободы - и это хорошо.


    Проблема в том, что "ещё одна степень свободы" выливается в описанные выше мною проблемы.
    1 авг 18, 12:53    [21620899]     Ответить | Цитировать Сообщить модератору
     Re: Зачем нужен await?  [new]
    hVostt
    Member

    Откуда:
    Сообщений: 14373
    kealon(Ruslan)
    как вы правильно после заметили это не контракт, а реализация. контрактом является возврат интерфейса в котором есть управление задачей и получение результата. Т.е. компилятор не может вызвать метод асинхронно, await - синтаксический сахар, он просто вызывает методы ожидания возвращаемого интерфейса и попутно трасирует в него часть своей реализации.


    Если мы говорим про C#, это довольно смелое утверждение насчёт "просто вызывает методы ожидания". Я спорил с Джоном Скитом на тему является ли await синтаксическим сахаром, и он меня убедил, что да, является. Но await принуждает компилятор строить конечный автомат без накладных расходов на количество кода в продолжении. А также разбирается с исключениями и контекстом синхронизации.

    В JavaScript да, это сахар, превращающийся в промисы.

    Конечно, из-за отсутствия контракта, компилятор не может сам сделать await, значит при его наличии, это можно было сделать, так?

    kealon(Ruslan)
    а как тогда должен себя вести код генерируемый компилятором?


    Он должен увидеть вызов асинхронного метода и выполнить его асинхронно, и не позволять дёргать асинхронные методы за пределами асинхронного контекста (асинхронного метода).

    kealon(Ruslan)
    всегда ждать завершения? тогда 21619662 вполне уместен


    Я не понимаю, почему до сих пор много людей путают конкурентность и асинхронность. Нет, не уместен.

    Давайте напомню, в JavaScript нельзя выполнить код параллельно. Можно выполнить
    1 авг 18, 13:00    [21620921]     Ответить | Цитировать Сообщить модератору
     Re: Зачем нужен await?  [new]
    WebSharper
    Member

    Откуда:
    Сообщений: 348
    https://softwareengineering.stackexchange.com/questions/328087/why-are-promises-not-awaited-by-default
    1 авг 18, 13:06    [21620952]     Ответить | Цитировать Сообщить модератору
     Re: Зачем нужен await?  [new]
    hVostt
    Member

    Откуда:
    Сообщений: 14373
    .. можно выполнить код асинхронно.

    kealon(Ruslan)
    запоминать что переменная не переменная и её нужно проверять? тогда встаёт вопрос эффективности, фактически придётся делать ленивый вызов при использовании переменной, следить за ней, что в массовом порядке накладно.


    При наличии контракта, видим, что метод асинхронный, значит выполняем его асинхронно. Т.е. компилятор сам вставляет await там, где он итак должен был быть написан программистом.
    1 авг 18, 13:09    [21620972]     Ответить | Цитировать Сообщить модератору
     Re: Зачем нужен await?  [new]
    hVostt
    Member

    Откуда:
    Сообщений: 14373
    WebSharper
    https://softwareengineering.stackexchange.com/questions/328087/why-are-promises-not-awaited-by-default


    SO
    Note that a function being async doesn't turn it into something completely different, it just enables some syntax. A normal function returning a promise is just as asynchronous as a function marked with async.

    The await serves as a warning sign "the world may have changed in the mean time".

  • 1. await may be easier than multi threading, but it's still very error prone. During code review you have to look at each await, thinking "does the function rely on any information obtained before the await still being the same? Is this guaranteed?". Without an explicit await, you have to do so at every function invocation.
  • 2. Backwards compatibility. With your proposal code behaves completely different if the browse/runtime supports awaiting or not.
  • 3. If your code doesn't want to deal with awaiting, it needs to insert an async at every call to an externally defined function, just in case it returns a promise.
  • 4. Performance. The runtime needs to insert an if result is a promise then await check at every method call.


  • Ok.

    1. мы хотим видеть вызовы await в коде, но IDE мог бы подсвечивать, находить и показывать такие вызовы.
    2. обратная совместимость, аргумент. ок.
    3. если я не хочу эвейтить, то для этого нужен отдельный синтаксис, потому что в 90% (если не больше) случаев нужно эвейтить.
    4. только для нетипизированных языков, таких как JavaScript, это является проблемой. но и она решается точно также, как решаются все остальные проблемы отсутствия типизации.

    в общем, пока только обратная совместимость выглядит как преграда.
    ну ещё несколько лет нужно, чтобы люди привыкли к парадигме.
    1 авг 18, 13:25    [21621062]     Ответить | Цитировать Сообщить модератору
     Re: Зачем нужен await?  [new]
    kealon(Ruslan)
    Member

    Откуда: Нижневартовск
    Сообщений: 3179
    hVostt,

    давайте в реализации шарпа, и плавно к нативу в плюсах из которого видно куда что прыгает

  • любой асинхронный метод в шарпе возвращает контракт IASync<T> на получение значения
    далее с ним надо что-то делать

    собственно await это такой сахар который одновременно ждёт вычисления IASync<T> и мониторит не отменили ли головной метод и если отменили "трубит" полученному контракту "СТОП"

    тут надеюсь всё понятно

  • как это всё выглядит изнутри плюсов:
    вызвали аснхронный метод, собственно он возвращает контракт IASync<T>
    и тут можно с ним делать что угодно: подождать вызвать другой метод и пр.

  • как это может быть в плане реализации асинхронного метода:
    тут куча вариантов: асинхронная функция ОС, запуск обёрнутой задачи в пул и пр. пр.


    теперь:
    hVostt
    Но await принуждает компилятор строить конечный автомат без накладных расходов на количество кода в продолжении. А также разбирается с исключениями и контекстом синхронизации.
    ничего он не выдумывает, он просто вставляет код ожидания

    hVostt
    Конечно, из-за отсутствия контракта, компилятор не может сам сделать await, значит при его наличии, это можно было сделать, так?
    у него только контракт (IASync<T>) и есть, он и вызывает один из его методов, на саму реализацию он не влияет

    hVostt
    kealon(Ruslan)
    а как тогда должен себя вести код генерируемый компилятором?


    Он должен увидеть вызов асинхронного метода и выполнить его асинхронно, и не позволять дёргать асинхронные методы за пределами асинхронного контекста (асинхронного метода).

    kealon(Ruslan)
    всегда ждать завершения? тогда 21619662 вполне уместен


    Я не понимаю, почему до сих пор много людей путают конкурентность и асинхронность. Нет, не уместен.

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

    a =AsyncMet1(d);
    c = a + b;
    

    куда физически вставлять await?
  • 1 авг 18, 13:29    [21621078]     Ответить | Цитировать Сообщить модератору
     Re: Зачем нужен await?  [new]
    kealon(Ruslan)
    Member

    Откуда: Нижневартовск
    Сообщений: 3179
    hVostt
    .. можно выполнить код асинхронно.

    kealon(Ruslan)
    запоминать что переменная не переменная и её нужно проверять? тогда встаёт вопрос эффективности, фактически придётся делать ленивый вызов при использовании переменной, следить за ней, что в массовом порядке накладно.


    При наличии контракта, видим, что метод асинхронный, значит выполняем его асинхронно. Т.е. компилятор сам вставляет await там, где он итак должен был быть написан программистом.
    ещё раз повторю: "асинхронный метод в реализации шарпа значит, что возвращается контракт на получение значения"
    т.е. в нативе это какой-то стаб который, например, кидает задачу в пул на выполнение своего кода и возвращает интерфейс по ожиданию его завершения\отмены\получению результата и пр.
    1 авг 18, 13:42    [21621120]     Ответить | Цитировать Сообщить модератору
     Re: Зачем нужен await?  [new]
    hVostt
    Member

    Откуда:
    Сообщений: 14373
    kealon(Ruslan)
    собственно await это такой сахар который одновременно ждёт вычисления IASync<T> и мониторит не отменили ли головной метод и если отменили "трубит" полученному контракту "СТОП"


    Ничего он не мониторит, а сигнализацию прерывания надо пробрасывать самому.

    Сахар превращает метод в конечный автомат. Это можно посмотреть в дизассемблере IL, для асинхронного и синхронного вызовов. С ручным ожиданием через GetAwaiter и через await. Сгенерированный код будет абсолютно разный.

    kealon(Ruslan)
  • как это всё выглядит изнутри плюсов:
    вызвали аснхронный метод, собственно он возвращает контракт IASync<T>
    и тут можно с ним делать что угодно: подождать вызвать другой метод и пр.

  • как это может быть в плане реализации асинхронного метода:
    тут куча вариантов: асинхронная функция ОС, запуск обёрнутой задачи в пул и пр. пр.


  • Из плюсов, да и в C# тоже, весь код, который генерит await можно написать и самостоятельно. Чудеса начинаются, когда среди кучи последовательных и вложенных await доходим до функций, выполняющих непосредственно I/O операции, которые и "отпускают" поток восвоясь. А когда результат будет получен, будет выдернут любой свободный поток, который продолжит выполнение оставшегося кода. Вот здесь суть, которую многие упускают, когда пытаются "на пальцах" строить свои объяснения того, как это устроено. Это и правда выглядит так, как будто оставшийся кусок метода после await тупо завернули в коллбек. Но это наивно так полагать.

    kealon(Ruslan)
    hVostt
    Но await принуждает компилятор строить конечный автомат без накладных расходов на количество кода в продолжении. А также разбирается с исключениями и контекстом синхронизации.
    ничего он не выдумывает, он просто вставляет код ожидания


    Куда вставляет? Кто код ожидания будет выполнять? Что там со стеком? Могу ли я ожидать огромное количество асинхронных операций, с небольшим количеством рабочих потоков?

    kealon(Ruslan)
    у него только контракт (IASync<T>) и есть, он и вызывает один из его методов, на саму реализацию он не влияет


    Пока нет такого контракта, который напрямую говорит, что этот метод является асинхронным. Для await подойдёт любой объект, у которого есть метод GetWaiter(). Этого недостаточно, так как те же Task используются и для многопоточного программирования, как часть TPL.


    kealon(Ruslan)
    ему вообще по барабану, у компилятора только контракт на ожидание выполнения непонятно чего

    a = await AsyncMet1(d);
    c = a + b;
    


    куда физически вставлять await?


    Вот сюда. И только при условии, что метод, в котором находится этот код помечен как async.
    1 авг 18, 14:28    [21621271]     Ответить | Цитировать Сообщить модератору
     Re: Зачем нужен await?  [new]
    hVostt
    Member

    Откуда:
    Сообщений: 14373
    kealon(Ruslan)
    т.е. в нативе это какой-то стаб который, например, кидает задачу в пул на выполнение своего кода и возвращает интерфейс по ожиданию его завершения\отмены\получению результата и пр.


    Т.е. будете ждать выполнение i/o операций на выделенном пуле потоков? Мдя...
    1 авг 18, 14:30    [21621278]     Ответить | Цитировать Сообщить модератору
     Re: Зачем нужен await?  [new]
    Valery_B
    Member

    Откуда: Москва
    Сообщений: 1692
    hVostt
    Вопрос такой. Почему бы вообще не отказаться от этого ключевого слова и необходимости его употребления, ведь компилятор может определить наличие вызова асинхронного метода и сам выполнить его асинхронно?

    Если я правильно понял, то ты хотел предложить не использовать await ?
    Но тогда как компилятор поймёт, до какого момента ему ждать ?

    private string GetExpensiveString()
    {
        Thread.Sleep(10000);
        return "Hello world";
    }
    
    private async void Button1Click(object sender, EventArgs e)
    {
        Task<string> task = new Task<string>(GetExpensiveString);
        task.Start();
        label1.Text = "Please wait";   
        string s = await task;
        label1.Text = s;
    }
    
    1 авг 18, 14:34    [21621296]     Ответить | Цитировать Сообщить модератору
     Re: Зачем нужен await?  [new]
    hVostt
    Member

    Откуда:
    Сообщений: 14373
    Valery_B
    Если я правильно понял, то ты хотел предложить не использовать await ?


    Не использовать ключевое слово await, в контексте, где его использование очевидно. Такой контекст есть.


    Valery_B
    private string GetExpensiveString()
    {
        Thread.Sleep(10000);
        return "Hello world";
    }
    
    // первый случай
    private async void Button1Click(object sender, EventArgs e)
    {
        // такое использование НЕ ОЧЕВИДНО
        // и это не асинхронный вызов!!
        Task<string> task = new Task<string>(GetExpensiveString);
        task.Start();
        label1.Text = "Please wait";   
        string s = await task;
        label1.Text = s;
    }
    
    // второй случай
    private async void Button1Click(object sender, EventArgs e)
    {
        // а такое очевидно
        // и это асинхронный вызов!
        label1.Text = "Please wait";   
        label1.Text = GetExpensiveStringAsync();
    }
    


    Первый случай это запуск таски в отдельном потоке, последующий await приводит только к асинхронному ожиданию (о чём было сказано 21619662), а не асинхронному выполнению.

    Во втором случае, функция помечена async, значит вызов любой асинхронной функции должен быть асинхронным, если это не указано каким-то определённым образом иначе.
    1 авг 18, 14:50    [21621364]     Ответить | Цитировать Сообщить модератору
     Re: Зачем нужен await?  [new]
    hVostt
    Member

    Откуда:
    Сообщений: 14373
    private async AwaitableResult<string> GetExpensiveStringAsync()
    {
        // можно было бы добавить
        /* await */ Task.Yield();
        //
        Thread.Sleep(10000);
        return "Hello world";
    }
    
    1 авг 18, 14:52    [21621377]     Ответить | Цитировать Сообщить модератору
     Re: Зачем нужен await?  [new]
    kealon(Ruslan)
    Member

    Откуда: Нижневартовск
    Сообщений: 3179
    hVostt
    kealon(Ruslan)
  • как это всё выглядит изнутри плюсов:
    вызвали аснхронный метод, собственно он возвращает контракт IASync<T>
    и тут можно с ним делать что угодно: подождать вызвать другой метод и пр.

  • как это может быть в плане реализации асинхронного метода:
    тут куча вариантов: асинхронная функция ОС, запуск обёрнутой задачи в пул и пр. пр.


  • Из плюсов, да и в C# тоже, весь код, который генерит await можно написать и самостоятельно. Чудеса начинаются, когда среди кучи последовательных и вложенных await доходим до функций, выполняющих непосредственно I/O операции, которые и "отпускают" поток восвоясь. А когда результат будет получен, будет выдернут любой свободный поток, который продолжит выполнение оставшегося кода. Вот здесь суть, которую многие упускают, когда пытаются "на пальцах" строить свои объяснения того, как это устроено. Это и правда выглядит так, как будто оставшийся кусок метода после await тупо завернули в коллбек. Но это наивно так полагать.
    не выдумывайте, там обычный линейный код
    hVostt
    kealon(Ruslan)
    пропущено...
    ничего он не выдумывает, он просто вставляет код ожидания


    Куда вставляет? Кто код ожидания будет выполнять? Что там со стеком? Могу ли я ожидать огромное количество асинхронных операций, с небольшим количеством рабочих потоков?
    ожидание выполняет реализатор контракта IAsync<T>
    в частности с IO, для этого достаточно текущую нить отдать "планировщику" и переключиться на выполнение другой задачи.
    Можете
    1 авг 18, 14:57    [21621396]     Ответить | Цитировать Сообщить модератору
     Re: Зачем нужен await?  [new]
    Valery_B
    Member

    Откуда: Москва
    Сообщений: 1692
    hVostt,

    Для меня как раз наоборот - первый случай абсолютно очевиден, а второй - наоборот.
    Не понятно, что должна сделать эта процедура выполняя первый и второй оператор.
    И в каком потоке.

    private async void Button1Click(object sender, EventArgs e)
    {
        // а такое очевидно
        // и это асинхронный вызов!
        label1.Text = "Please wait";   
        label1.Text = GetExpensiveStringAsync();
    }
    
    1 авг 18, 15:02    [21621414]     Ответить | Цитировать Сообщить модератору
    Топик располагается на нескольких страницах: [1] 2 3 4 5 6 7 8 9 10 11   вперед  Ctrl      все
    Все форумы / WinForms, .Net Framework Ответить