Я думал, что задача GetData, зарегистрированная в Page_Load, не будет блокировать загрузку Index.aspx, поскольку это асинхронная задача; Через 5 секунд после рендеринга страницы lblData устанавливается и отражается в Index.aspx.

Однако в моем случае загрузка Index.aspx заблокирована на 5 секунд, ожидая завершения async GetData. Только через 5 секунд визуализируется Index.aspx.

Ожидается ли это? Или GetData работает синхронно, потому что я сделал что-то не так?

// Index.aspx.cs
public partial class Index : Page
{
    protected string lblData;
    protected void Page_Load(object sender, EventArgs e)
    {
        RegisterAsyncTask(new PageAsyncTask(GetData));
        ExecuteRegisteredAsyncTasks();
    }

    public async Task GetData()
    {
        await Task.Delay(5000);
        lblData = "Hello world!";
    }
    // ...
}

Я добавил Async="true" в Index.aspx.

4
lzl124631x 26 Апр 2016 в 13:49

3 ответа

Лучший ответ

«Асинхронный» - это модификатор. Вы всегда должны спрашивать "асинхронность относительно чего?"

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

Это не асинхронно относительно рендеринга страницы на клиенте или даже самого отдельного запроса - обработка запроса по-прежнему полностью синхронна и будет отправлена только тогда, когда будет готов весь ответ (если вы не используете явные Flush es, но это уже целая банка червей). Фактически, весь смысл await состоит в том, чтобы позволить вашему коду вести себя так, как если бы он был синхронным, но в то же время асинхронным по отношению к потокам, вводу-выводу, пользовательскому интерфейсу и т. Д. await - явная точка синхронизации.

Фактически, именно поэтому вы в первую очередь используете асинхронную инфраструктуру. Если вы использовали асинхронные задачи без RegisterAsyncTask, запрос завершился бы до того, как ответ будет полностью выполнен. Инфраструктура позволяет вам освобождать рабочие потоки, пока они вам не нужны, сохраняя при этом весь соответствующий контекст запроса готовым к тому времени, когда вы вернетесь из своей асинхронной работы. Это похоже на использование await в методе Main консольного приложения - если инфраструктура не готова, await просто означает return someTask; без "и вернуться сюда, когда задача сделана ».

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

4
Luaan 26 Апр 2016 в 11:21

Вероятно, он работает асинхронно, но он все еще «код позади», и этот код будет запущен и завершен на сервере до того, как любая отрисованная страница будет отправлена в браузер.

Если вы хотите, чтобы ваша сетка динамически заполнялась после загрузки страницы в браузере, вам нужно использовать JavaScript и WebMethods или WebAPI или что-то подобное.

0
Alexander 26 Апр 2016 в 11:10

Согласно MSDN, вы все делаете правильно. Я предполагаю, что вы ошибочно предполагаете, что страница будет загружена / обработана и возвращена клиенту до завершения асинхронной операции, определенной в функции GetData - если это так, это неверно.

Жизненный цикл (в то время как асинхронный) по-прежнему не возвращается клиенту, пока не будет выполнена вся работа. Вот SO Q & amp;, что может иметь больше смысла. Еще лучшее объяснение Скотта Хансельмана здесь.

1
Community 23 Май 2017 в 12:23