Любой недостаток использования ExecuteReaderAsync из C# AsyncCTP

StackOverflow https://stackoverflow.com/questions/9432647

Вопрос

Есть несколько статей, в которых указывается, что асинхронные вызовы базы данных — плохая идея в .NET.

В C# Async CTP есть System.Data.SqlClient.SqlCommand расширение называется ExecuteReaderAsync.У меня есть некоторые операции, как показано ниже, в моем существующем коде:

var connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["hubConnectionString"].ConnectionString;

using (var conn = new SqlConnection(connectionString)) {
    using (var cmd = new SqlCommand()) {

        cmd.Connection = conn;
        cmd.CommandText = "sp$DetailsTagsGetAllFromApprovedPropsWithCount";
        cmd.CommandType = System.Data.CommandType.StoredProcedure;

        conn.Open();

        var reader = cmd.ExecuteReader();
        while (reader.Read()) {

            //do the reading

        }

        conn.Close();
    }
}

В моем коде есть несколько подобных операций.Итак, у меня есть мысли о преобразовании их в асинхронные.

Но с другой стороны, я не вижу особой привлекательности в этом подходе (может быть, я не в том направлении смотрю, кто знает!).

Итак, есть ли какие-либо недостатки в использовании этой новой модели асинхронного программирования?

Редактировать:

Предполагая, что я реорганизую код, как показано ниже:

public async Task<IEnumerable<Foo>> GetDataAsync() { 

    List<Foo> foos = new List<Foo>();

    var connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["hubConnectionString"].ConnectionString;

    using (var conn = new SqlConnection(connectionString)) {
        using (var cmd = new SqlCommand()) {

            cmd.Connection = conn;
            cmd.CommandText = "sp$DetailsTagsGetAllFromApprovedPropsWithCount";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            conn.Open();

            var reader = await cmd.ExecuteReaderAsync();
            while (reader.Read()) {

                //do the reading
                //create foos

            }

            conn.Close();
        }
    }

    return foos;

}

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

Вот что я имею в виду.

Это было полезно?

Решение

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

В ситуации с высоким трафиком (и это единственное, что имеет значение) пулу потоков не придется ждать «внедрения» новых потоков.Асинхронное выполнение команд SQL важно не только с точки зрения работоспособности запросов/потоков веб-сервера, но также с точки зрения общего времени жизни/задержки запроса:некоррелированные вызовы БД могут выполняться параллельно, а не последовательно.Одно только это обычно приводит к значительному уменьшению задержки HTTP-запроса, которую ощущает пользователь.Другими словами, ваши страницы загружаются быстрее.

Однако небольшой совет:Команда SQL не является по-настоящему асинхронной, пока вы не включите Asynchronous Processing=true в строке подключения.Хотя это не установлено (и по умолчанию не установлено, Редактировать:начиная с .NET Framework < 4.5. Asynchronous Processing больше не требуется) ваши «асинхронные» вызовы BeginExecuteReader являются не чем иным, как притворством, вызов запустит поток и заблокирует что нить.Когда включена настоящая асинхронная обработка в строке подключения тогда вызов действительно асинхронный, а обратный вызов основан на завершении ввода-вывода.

Предупреждение:асинхронная команда SQL завершается, как только первый результат возвращается клиенту, и информационные сообщения считаются результатом.

create procedure usp_DetailsTagsGetAllFromApprovedPropsWithCount
as
begin
print 'Hello';
select complex query;
end

Вы потеряли все преимущества асинхронности.А print создает результат, который отправляется обратно клиенту, который завершает асинхронную команду, и выполнение на клиенте возобновляется и продолжается с помощью «reader.Read()».Сейчас что будет блокироваться до тех пор, пока сложный запрос не начнет давать результаты.Ты спрашиваешь 'кто ставит print в процедуре? но print может быть замаскирован во что-то другое, возможно, в нечто столь же невинное, как INSERT который выполняет без сначала выпустив SET NOCOUNT ON.

Другие советы

Я заметил, что на следующий вопрос не ответили:

Итак, есть ли какие-либо недостатки в использовании этой новой модели асинхронного программирования?

А недостаток который очень минимальный (меньший процессор/меньшая память), потому что существует вероятность запуска любого кода после оператора await. может выполняется в отдельном потоке, существует конечный автомат для хранения состояния текущего потока, чтобы продолжение работы можно было обрабатывать в другом потоке.Вы можете прочитать больше о Конечный автомат await/async в блоге Dixin - Понимание C# async/await (1) Компиляция.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top