Любой недостаток использования ExecuteReaderAsync из C # AsyncCTP - PullRequest
27 голосов
/ 24 февраля 2012

Есть несколько статей, которые указывают, что асинхронные вызовы базы данных являются плохой идеей в .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, он немедленно возвращается к своему вызывающему абоненту независимо от состояния операции.Когда он заканчивается, он возвращается и запускает код продолжения.

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

Ответы [ 2 ]

54 голосов
/ 24 февраля 2012

Я не согласен с Рикой в ​​этом. Команды асинхронной БД не только хороши, они важны для достижения масштаба, пропускной способности и задержки. Его возражения по поводу времени нарастания пула потоков относятся только к веб-серверу с низким объемом трафика.

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

Однако совет: команда SQL не будет действительно асинхронной, пока вы не включите Asynchronous Processing=true в строке подключения. Хотя это не установлено (и по умолчанию это не так, Редактировать: начиная с .NET Framework <4.5. <a href="http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnectionstringbuilder.asynchronousprocessing.aspx" rel="noreferrer">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.

0 голосов
/ 26 января 2018

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

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

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

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