async + очікувати == синхронізація?


24

Натрапив на цей пост, в якому йдеться про створення асинхронних веб-запитів.

Тепер простоту в сторону, якщо в реальному світі все, що ви робите, - це зробити запит на асинхронізацію і дочекатися його в наступному рядку, чи це не те, що в першу чергу робити виклик синхронізації?


5
Не зовсім. Ваш код є синхронним в тому сенсі, що нічого не відбувається, поки ви не отримаєте результат. Однак під ним ви, ймовірно, відмовились від потоку, на якому працювали, поки не повернувся метод асинхронізації, а потім призначили інший потік для продовження виконання.
R0MANARMY

2
це так, але за допомогою async ви можете зробити ще одну асинхронізацію одночасно, а потім чекати 2, синхронізація цього неможлива
храповик урод

Ось стаття ( tomasp.net/blog/async-compilation-internals.aspx ), де обговорюються деякі недоліки асинхронізації в C # - це частина серії, що охоплює асинхронне програмування в C # і F #.
Павло

@ratchetfreak: Так, це само собою зрозуміло, якщо ви робите кілька дзвінків.
Mrchief

@ R0MANARMY: Якщо ваш додаток робить інші речі, тоді так і async + очікування дозволяє це. Акім каже, що найкраще! Але уявіть, що код не знаходиться в обробці кнопки_click або будь-якому такому обробнику подій з цього питання. Якщо хтось наосліп копіює код (async + очікування рядків) на будь-який метод, це може призвести до помилкового враження, що ваш код є асинхронним, але насправді це може бути не так.
Mrchief

Відповіді:


32

Ні, async + await != syncчерез продовження

Від MSDN "Асинхронне програмування за допомогою Async і Await (C # і Visual Basic)"

Методи асинхронізації призначені для неблокуючих операцій. Вираз очікування в методі асинхронізації не блокує поточний потік під час запуску очікуваного завдання. Натомість вираз підписує решту методу у вигляді продовження і повертає керування виклику методу async .

Наприклад, виконання асинхронізації не блокує потік інтерфейсу, а Some TextBox.Textоновиться після завершення завантаження

private async void OnButtonClick()
{
   SomeTextBox.Text = await new WebClient().DownloadStringTaskAsync("http://stackoverflow.com/");
}

Дуже красиво сказано!
Mrchief

Чи можете ви пояснити більш детально. Ви говорите ... що без цього ... ви не змогли б взаємодіяти з користувальницьким інтерфейсом ... як це було б в основному потоці. Це означає, що це стає застосовним лише у програмі типу додатків, призначеній для Інтернету, де взаємодія відокремлена від потоку веб-сервера. Отже, в оболонці гайки це стає важливим лише, тобто не синхронізувати *, коли вашою основною ниткою є запущена нитка. Хіба це не спричинило б несподівану поведінку, тобто в додатку (1 головний потік) натиснули дві кнопки .. але ви повинні мати можливість натиснути на 1 без першого завершення?
Seabizkit

Про що Console.WriteLine(await GetStringOverNetwork());? Що робити, якщо вам потрібен вихід асинхронного виклику? Чи блокується програма при першому доступі, навіть якщо потік потенційно може продовжувати виконання?
Андрій

6

Ні, це не те саме.

Ваш asyncкод коду чекає, коли awaitдзвінок повернеться, щоб продовжити, однак решта вашої заявки не чекає і може продовжуватись як звичайно.

На відміну від цього, синхронний виклик змусить всю вашу програму або потік зачекати, поки код не завершить виконання, щоб продовжувати роботу з будь-чим іншим.


не вдалося здійснити виклик синхронізації, оскільки очікує async +?
храповик урод

@ratchetfreak Я думаю, що є деякі накладні настройки, щоб налаштувати очікувати / асинхронізувати, тому я не думаю, що ви хочете кодувати всю свою програму разом із цим. Я використовую його лише для виконання потенційно довгих блоків коду, щоб він не блокував мої програми. :)
Рейчел

5

Будь ласка, дозвольте мені уточнити речі щодо асинхронізації / очікування.

При появі очікування машина, що лежить в основі, дозволяє негайно повернути управління. Потім, коли очікуваний виклик завершений, машина, що лежить в основі, дозволяє виконувати виконання по лінії після очікуваного дзвінка.

Тому блок асинхронізації не заблокований і не чекає завершення очікуваного дзвінка; Керування повертається негайно, коли зустрічається команда очікування.

Машина, що лежить в основі, є частиною "магії", яка полягає в застосуванні асинхронізування / очікування, яке не буде використане та пропущено.


2

Я наткнувся на це з тим же запитанням на увазі, але, прочитавши відповіді, питання, здається, затрималося, переплутане посиланнями на "магію під кришкою".

З вищезазначеного асинхронного програмування :

  • The asyncКлючове слово перетворює метод як метод асинхронного, що дозволяє використовувати awaitключове слово в своєму тілі.
  • Коли await ключове слово застосовано, воно призупиняє метод виклику і повертає контроль своєму абоненту до завершення очікуваного завдання.
  • awaitможе використовуватися лише всередині asyncметоду.

Чи awaitзаблокований контекст, який зустрічається ?

  • Так . Це по суті локальний бар'єр синхронізації для підтримання відомого стану в контексті виконання; за винятком того, що інші контексти, якщо такі є, не приєднуються.

Чи блокується решта програми на await?

  • Це залежить від того, як написана ваша заява. Якщо це ряд залежних awaitзавдань редагування, що запускаються послідовно в одному контексті (див.: Спроба зрозуміти деяку поведінку асинхронізації / очікування )

    await asyncCall1();
    await asyncCall2();  // waits for asyncCall1() to complete

    таким чином кожен await би блокував нерест наступного.

    З іншого боку, ті ж залежні завдання, запущені паралельно, виконувались б паралельно, а контекст блокувався б лише при респ. await:

    Task<int> t1 = asyncCall1();
    Task<string> t2 = asyncCall2();  // runs in parallel with asyncCall1()
    int val = await t1;
    string str = await t2;  // waits for asyncCall1() to complete

    Загалом, awaitприносить виконання зовнішньому контексту, звідки викликається поточний контекст. Однак якщо зовнішній контекст сам чекає на поточний, то це як послідовний awaits у тому ж контексті.

Отже, щоб скористатись asyncперевагами, потрібно розробити додаток для запуску декількох паралельних контекстів (інтерфейс користувача, клієнт даних тощо), тоді awaitв одному контексті приводиться до виконання інших контекстів, так що вся програма не блокується для окремої людини await.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.