Чем отличаются эти асинхронные вызовы методов? - PullRequest
0 голосов
/ 15 декабря 2018

Я читал главу о ключевых словах await и async в моей книге на C #.Он в основном объяснял такие вызовы методов, когда вызывающий абонент использует ключевое слово await для ожидания завершения вызываемого метода.

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

static async Task Main(string[] args)
{
    WriteText();

    await WriteTextAsync();

    WriteTextAsync().Wait();
}

static void WriteText()
{
    Thread.Sleep(3_000);
    Console.WriteLine("Hello");
}

static async Task WriteTextAsync()
{
    await Task.Run(() =>
    {
        Thread.Sleep(3_000);
        Console.WriteLine("Hello");
    });
}

Ps: Если вызывающий поток метода ожидает завершения метода в любом случае, то это также может быть обычный вызов?

Ответы [ 3 ]

0 голосов
/ 15 декабря 2018

Я буду ссылаться на:

//Call 1
WriteText();

//Call 2    
await WriteTextAsync();

//Call 3
WriteTextAsync().Wait();

При первом вызове проблем не возникает, если вы хотите сделать синхронное ожидание.В консольном приложении это вполне нормально.

Проблема возникает в программах с пользовательским интерфейсом или в тех, которые требуют наилучшего использования ресурсов ЦП, наиболее распространенным случаем являются веб-приложения.

Вызов 2 с использованием await выполняет асинхронное ожиданиеза результат WriteTextAsync.Само по себе это нормально и считается нормальным.Тем не менее, WriteTextAsync является очень хорошим примером того, что вы должны никогда делать:

static async Task WriteTextAsync()
{
    // Let's create a Thread
    await Task.Run(() =>
    {
        // just to block it completely, having it do nothing useful
        Thread.Sleep(3_000);
        Console.WriteLine("Hello");
    });
}

Скорее, автор должен был использовать:

static async Task WriteTextAsync()
{
    // Let's *not* create a new thread
    await Task.Delay(3_000);
    Console.WriteLine("Hello");
}

Возможноони должны были указать на это дальше, но вы не дали нам название книги, чтобы знать это.

Вызов номер 3 - это то, что вам нужно сделать, когда вызывающий метод не может быть * 1021.* один, и вам нужно вызвать async метод, так:

// Think that for some reason you cannot change the signature, 
// like in the case of an interface, and an async void would make your code
// never complete correctly
static void Main(string[] args)
{
    //Call 3
    WriteTextAsync().Wait();
}

В целом, я бы посоветовал вам найти лучшую книгу.Примеры легче понять, когда фактически требуется асинхронный код.

0 голосов
/ 15 декабря 2018

Насколько я понимаю ваш вопрос:

Если программа ожидает ответа в строке await WriteTextAsync () , что будет выгодно?

Для клиентских приложений, таких как Windows Store, рабочий стол Windows и приложения для Windows Phone, основным преимуществом асинхронности является оперативность.Эти типы приложений используют асинхронность в основном для обеспечения отзывчивости интерфейса.Для серверных приложений основным преимуществом асинхронности является масштабируемость.

Я попытаюсь объяснить с точки зрения веб-приложения.

Предположим, что ваше веб-приложение зависит от внешних ресурсов, таких как база данных.вызов, когда клиент инициирует запрос. ASP.NET берет один из потоков своего пула потоков и назначает его этому запросу.Поскольку он написан синхронно, обработчик запросов будет вызывать этот внешний ресурс синхронно.Это блокирует поток запроса до тех пор, пока не будет возвращен вызов к внешнему ресурсу.На рисунке 1 показан пул потоков с двумя потоками, один из которых заблокирован в ожидании внешнего ресурса.

enter image description here

Рисунок 1 Синхронное ожидание внешнего ресурса

Теперь, если третий клиент запрашивает одновременно, то в пуле потоков нет доступных потоков для назначения третьего запроса.

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

Когда действия сервера запросов завершаются, вызов базы данных linke завершается, а затем SynchronizationContext возобновляет этот вызов и возвращает клиенту сообщение об отдыхе.

Сильфонное изображение в простой аналогии с вызовом aync

enter image description here

Много всего происходит под капотом.Я написал эту статью из Асинхронное программирование: введение в Async / Await на ASP.NET и мое понимание.Настоятельно рекомендуется иметь четкое понимание перед использованием async-wait.

0 голосов
/ 15 декабря 2018

Когда вы говорите WriteText(), WriteText() будет блокировать ваш текущий поток, пока он не завершится, поскольку он является синхронным.

Когда вы говорите await WriteTextAsync(), вы создадите новый поток и не будете блокировать вычисления, которые не зависят от результата WriteTextAsync(). РЕДАКТИРОВАТЬ: Согласно Microsoft Docs Когда вы говорите await WriteTextAsync(), компилятор планирует остаток от Main() для выполнения после завершения WriteTextAsync().Затем предполагается вернуть элемент управления вызывающей стороне асинхронного метода.Но кто звонит по Main()?Поскольку получается , async Main() нет - на самом деле это тот же синхронный Main() - и это просто синтаксический сахар для того, чтобы не писать .Wait() внутри него.Таким образом, в этом случае этот вызов эквивалентен WriteTextAsync().Wait()!

Наконец, когда вы говорите WriteTextAsync().Wait(), вы снова блокируете текущий поток и ждете результата WriteTextAsync().

...