Looking for c# Keywords? Try Ask4Keywords

C# Language Оператор ожидания и ключевое слово async


пример

await оператора и ключевое слово async объединяются:

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

Противоположность не всегда верна: вы можете пометить метод как async не используя await в своем теле.

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

Примечание: вы не можете ждать метода async, который ничего не возвращает (void).

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

Если мы проигнорируем некоторые важные детали, компилятор примерно сделает это за вас:

public async Task<TResult> DoIt()
{
    // do something and acquire someTask of type Task<TSomeResult>  
    var awaitedResult = await someTask;
    // ... do something more and produce result of type TResult
    return result;
}

будет выглядеть так:

public Task<TResult> DoIt()
{
    // ...
    return someTask.ContinueWith(task => {
        var result = ((Task<TSomeResult>)task).Result;
        return DoIt_Continuation(result);
    });
}

private TResult DoIt_Continuation(TSomeResult awaitedResult)
{
    // ...
}

Любой обычный метод можно превратить в async следующим образом:

await Task.Run(() => YourSyncMethod());

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

Но здесь есть очень важное замечание: асинхронный не всегда означает одновременный (параллельный или даже многопоточный). Даже в одном потоке async await до сих пор позволяет использовать асинхронный код. Например, см. Этот настраиваемый планировщик задач . Такой «сумасшедший» планировщик задач может просто превращать задачи в функции, которые вызывают в обработке цикла сообщений.

Нам нужно спросить себя: какой поток выполнит продолжение нашего метода DoIt_Continuation ?

По умолчанию оператор await выполняет выполнение продолжения с текущим контекстом синхронизации . Это означает, что по умолчанию для продолжений WinForms и WPF в потоке пользовательского интерфейса. Если по какой-то причине вам нужно изменить это поведение, используйте метод Task.ConfigureAwait() :

await Task.Run(() => YourSyncMethod()).ConfigureAwait(continueOnCapturedContext: false);