Вот как работает асинхронный поток - PullRequest
0 голосов
/ 18 мая 2018

Я новичок в асинхронном программировании на c # и прочитал несколько хороших статей по этому вопросу (см. здесь , здесь и здесь для примеров).Я думаю, что у меня есть понимание того, как это работает, но я надеюсь, что кто-то может подтвердить, что я на правильном пути.

Если я правильно понимаю, асинхронное программирование работает так:

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

Асинхронный метод назначается типовой задаче.Задача - это метод, который выполняется, или, в нашем случае, это приготовление пищи.Тип возврата - это тип, который будет возвращать Задача.После того, как задача назначена, текущий метод игнорирует ее, зная, что она выполняется.

Команда await - это место, где вызывающий метод запрашивает результаты задачи.Чтобы продолжить наш пример, шеф-повар просит приготовителя приготовить нарезанные овощи.Если задание выполнено, выдается результат, и вызывающий метод продолжает выполняться.Если задача еще не завершена, вызывающий метод должен дождаться ее завершения.Другими словами, если приготовитель еще не закончил нарезать овощи к тому времени, когда шеф-повар нуждается в них, шеф-повар должен подождать, прежде чем он сможет продолжить готовить рецепт.(Я знаю, что метафора здесь разрушается, потому что настоящий шеф-повар ушел бы и сделал что-то еще, но это только для упрощения объяснения.)

Чтобы использовать команду await, метод должен быть асинхронным методом,В приведенном выше примере вызывающий метод является асинхронным методом.Таким образом, когда он нажимает на команду await, управление возвращается к своему вызывающему методу, который будет продолжать работать, пока не завершит или не встретит собственное ожидание.

Итак, теперь у нас есть метод A, который вызывает асинхронный метод B, который вызывает асинхронный метод C. Метод B останавливается в ожидании, ожидая результатов от метода C. Оба метода A и C работают асинхронносейчас, пока метод B ждет результатов.Как только метод C вернет результаты, метод A и B будут работать асинхронно до тех пор, пока либо метод B не завершится, либо метод A не решит, что ему нужно ожидать результатов от метода B. Обратите внимание, что метод B может не нуждаться в возврате результатов, поэтому метод A можетзавершить до выполнения метода B.

Правильно ли это звучит, или управление переместится с A на B, а затем вернется к A только тогда, когда будет нажата кнопка ожидания?Таким образом, если у A нет своего собственного ожидания, он завершит работу до того, как контроль вернется к B.

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

1 Ответ

0 голосов
/ 18 мая 2018

Каждый раз, когда используется await, метод в этот момент компилируется в отдельный метод , и оригинальный метод завершается в этой точке (async / await является синтаксическим сахаром).Сгенерированный метод зарегистрирован как продолжение Task, к которому относится await.Если в данном методе существует более одного await, то для каждого await.

применяется одна и та же процедура. Каждый раз, когда для описания метода используется async, это означает, что метод поддерживает await и можно скомпилировать в серию продолжений.Первая часть метода вызывается inline с вызывающим кодом, но части, сгенерированные как часть await, будут поставлены в очередь в планировщике TPL по умолчанию (по порядку, как части завершены) и будут вызываться в соответствии с настройкой этого планировщика.,Task, возвращенный методом async, будет представлять метод в целом (таким образом, метод может быть отменен при любом await в методе), и любое продолжение, зарегистрированное для этого Task, будет поставлено в очередь в TPL.планировщик по умолчанию, если / когда завершается Task.

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

Async / Await

public void Main()
{
    var result = Calculate(1, 3).Result;

    async Task<int> Calculate(int a, int b)
    {
        var c = await Add(a, 5);
        var d = await Add(b, 3);

        return await Add(c, d);
    }

    async Task<int> Add(int a, int b)
    {
        return a + b;
    }
}

Pure TPL

public void Main()
{
    const int a = 1;
    const int b = 3;

    var t1 = Task.Run(() => new
        {
            c = a + 5
        }
    );

    var t2 = t1.ContinueWith(t =>
        new
        {
            c = t.Result.c,
            d = b + 3
        }
    );

    var t3 = t2.ContinueWith(t =>
        t.Result.c + t.Result.d
    );

    var result = t3.Result;
}
...