Мой код OnAppearing выглядит так. Я не понимаю, для чего это добавлено:

`await Task.Yield()`

Может кто-нибудь объяснить, что это делает?

    protected override async void OnAppearing()
    {
        base.OnAppearing();
        Utils.SetState(Settings.mode.Text(), vm.Mode);
        vm.CfsLabel = Settings.cfs.Text();

        SetMode(Settings.mode.Text());
        Subscribe();
        ContentPageStack.IsVisible = true;
        if (!openedOnce)
        {
            // can someone explain what the following line
            // is doing here in the code. What's the Task
            // that it refers to and what does Yield do? 
            await Task.Yield();

            await scroll.ScrollToAsync(0, 0, false);
            openedOnce = true;
        }
        if (App.devIsUser)
            Analytics.TrackEvent(VersionTracking.CurrentVersion + " - On Appearing - home page");
    }
0
Alan2 23 Май 2019 в 12:54

2 ответа

Лучший ответ

В данном конкретном случае await Task.Yield ничего полезного не делает. Вероятно, это ошибочная попытка обработать сообщения Win32, такие как WM_PAINT. То есть, "бедняга DoEvents".

await Task.Yield используется для принудительной асинхронности. Это способ заставить await вести себя асинхронно, возвращаясь к вызывающей стороне. Он также сразу ставит в очередь оставшуюся часть метода для запуска.

Причина, по которой он не работает как DoEvents бедняка, заключается в том, что очередь сообщений Win32 имеет приоритет. Вот что на самом деле делает await Task.Yield в данном конкретном случае:

  • Поставляет в очередь продолжение метода async в текущий контекст (пользовательский интерфейс SynchronizationContext), который помещает продолжение в очередь сообщений Win32.
  • Возвращает из метода async. Поскольку это обработчик событий, он возвращается к циклу обработки сообщений Win32.
  • Цикл обработки сообщений Win32 извлекает следующее сообщение из своей очереди. Поскольку очередь имеет приоритет, она всегда пропускает обычные сообщения Win32 и принимает сообщение продолжения.
  • Цикл обрабатывает сообщение, которое запускает продолжение метода async, поэтому обработчик событий возобновляет выполнение с того места, где он остановился.
1
Stephen Cleary 23 Май 2019 в 14:36

Я думаю, что документы Microsoft дают вам четкое представление о том, что они делают, когда вы читаете о Task.Yield говорит:

Создает ожидаемую задачу, которая асинхронно возвращается к текущему контексту при ожидании.

Возвращает < Сильный > YieldAwaitable

Контекст, который при ожидании асинхронно переходит обратно в текущий контекст во время await. Если текущий SynchronizationContext не равен нулю, он обрабатывается как текущий контекст. В противном случае планировщик задач, связанный с текущей выполняющейся задачей, рассматривается как текущий контекст.

Это в основном означает, что когда вы используете await Task.Yield в асинхронном методе, это заставит метод завершиться асинхронно. И если есть контекст синхронизации доступно, он выполнит оставшуюся часть выполнения метода обратно в этот контекст.

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

0
FreakyAli 23 Май 2019 в 10:22