Выполнение хранимой процедуры асинхронно, не ожидая ее и не блокируя пользовательский интерфейс - PullRequest
1 голос
/ 07 мая 2019

У меня есть несколько хранимых процедур, которые ВСТАВЛЯЮТ или ОБНОВЛЯЮТ в базу данных в моем приложении веб-форм ASP.NET.Я хочу, чтобы эти запросы выполнялись, но я не хочу, чтобы пользовательский интерфейс или выполнение страницы ожидали их завершения.Они не занимают много времени (намного меньше секунды), но это секунда, в течение которой пользователь должен ждать загрузки страницы.

Я обычно смотрю на вставку журнала или истории в таблицу.Просмотр страницы пользователя не зависит от выполнения или результатов запроса.

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

private async Task<string> DoTransaction()
{
    string value = "";

    using (SqlConnection objCS = DB.AdminNET())
    {
        await objCS.OpenAsync();
        using (SqlTransaction t = objCS.BeginTransaction())
        using (SqlCommand objCommand = new SqlCommand("WAITFOR DELAY '00:00:05'; EXEC logtiming @line", objCS, t))
        {
            try
            {
                objCommand.Parameters.Add("@line", SqlDbType.VarChar).Value = "log me";
                await objCommand.ExecuteNonQueryAsync();
            }
            catch
            {
                t.Rollback();
                throw;
            }

            t.Commit();

            value = "done";
        }
    }

    return value;
}

protected async void Page_Load(object sender, EventArgs e)
{
    await DoTransaction(g);
}

Этот код вставит мои тестовые данные после введенной задержки.Тем не менее, он удерживает весь ответ страницы пользователю до тех пор, пока не закончится задержка.В идеале я хотел бы, чтобы страница немедленно возвращалась пользователю, а через пять секунд я увижу свои результаты в таблице.Является ли ExecuteNonQueryAsync () неправильным инструментом для этого?Или я могу внести некоторые изменения, которые я еще не нашел, например."не ждите"?

1 Ответ

4 голосов
/ 07 мая 2019

Кажется, что ExecuteNonQueryAsync () ... блокирует пользовательский интерфейс до тех пор, пока оба не будут завершены.

Да, именно так работает ASP.NET.Все остальные HTTP-серверы, такие как ASP.NET Core и Node.js, работают одинаково: отправляется только один ответ, и он отправляется только после завершения обработчика запроса - это правда, является ли обработчик синхронным или асинхронным.

Для получения дополнительной информации см. Мою статью об асинхронном ASP.NET ;соответствующий раздел:

Асинхронный код не является «серебряной пулей»

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

Когда некоторые разработчики узнают об асинхронности и ожидании, они полагают, что код сервера «уступает» клиенту (например, браузер).Однако асинхронное ожидание в ASP.NET только «уступает» среде выполнения ASP.NET;протокол HTTP остается неизменным, и у вас все еще есть только один ответ на запрос.Если вам потребовался SignalR или AJAX или UpdatePanel до асинхронного / await, вам все равно потребуется SignalR или AJAX или UpdatePanel после асинхронного / await.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...