web-dev-qa-db-fra.com

Tout inconvénient lié à l'utilisation de ExecuteReaderAsync à partir de C # AsyncCTP

Certains articles indiquent que les appels de base de données async sont une mauvaise idée dans .NET. 

Sur CTP Async C #, il existe une extension System.Data.SqlClient.SqlCommand appelée ExecuteReaderAsync. J'ai quelques opérations comme ci-dessous sur mon code existant:

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();
    }
}

Il y a plusieurs opérations comme celle-ci sur mon code. Donc, je pense à convertir ceux-ci en async. 

Mais d'un autre côté, je ne vois pas beaucoup d'attrait dans cette approche (peut-être que je ne regarde pas la bonne direction, qui sait!).

Alors, l'utilisation de ce nouveau modèle de programmation asynchrone présente-t-elle des inconvénients?

Modifier:

En supposant que je refactorise le code comme ci-dessous:

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;

}

D'après ce que j'ai compris du mot-clé wait, le code, qui le suit, est converti en continuation. De plus, lorsqu'il atteint le mot-clé wait, il retourne immédiatement à l'appelant, quel que soit le statut de l'opération. Quand il a fini, il revient et déclenche le code de continuation. 

C'est ce que j'ai en tête.

27
tugberk

Je ne suis pas d'accord avec Ricka à ce sujet. Les commandes de base de données async sont non seulement bonnes, mais également essentielles pour obtenir une latence, un débit et. Son objection concernant le temps de montée en puissance du pool de threads ne s'applique qu'à un serveur Web dont le volume de trafic est faible. 

Dans une situation de trafic intense (le seul qui compte), le pool de threads n'aura pas à attendre pour "injecter" de nouveaux threads. Effectuer les commandes SQL de manière asynchrone est important non seulement du point de vue de la santé des requêtes/threads du serveur Web, mais également du point de vue de la durée de vie/du temps de demande total: les appels de base de données non corrélés peuvent être effectués en parallèle, et non séquentiellement. Cela seul se traduit généralement par des améliorations considérables de la latence de la requête HTTP, telle que constatée par l'utilisateur. En d'autres termes, vos pages se chargent plus rapidement.

Un conseil cependant: la commande SQL n’est vraiment asynchrone que lorsque vous activez Asynchronous Processing=true sur la chaîne de connexion. Bien que cela ne soit pas défini (et par défaut, Edit: à partir de .NET Framework <4.5. Asynchronous Processing n'est plus requis, vos appels 'asynchrones' à BeginExecuteReader ne sont qu'un simulacre, l'appel lancera un fil et bloquera le fil that. Lorsque le traitement asynchrone vrai est activé dans la chaîne de connexion, l'appel est véritablement asynchrone et le rappel est basé sur l'achèvement de IO. 

Un mot d'avertissement: une commande SQL asynchrone se termine dès que le résultat first est renvoyé au client et que les messages d'information sont comptabilisés en tant que résultat.

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

Vous avez perdu tous les avantages de l'async. La print crée un résultat qui est renvoyé au client, ce qui complète la commande asynchrone et l'exécution sur le client reprend et se poursuit avec le paramètre 'reader.Read ()'. Maintenant, that bloquera jusqu'à ce que la requête complexe commence à produire des résultats. Vous demandez 'qui met print dans la procédure?' mais la print peut être déguisée en quelque chose d'autre, peut-être quelque chose d'aussi innocent qui ressemble à une INSERT qui exécute sans que ait d'abord émis un SET NOCOUNT ON .

54
Remus Rusanu

Je remarque que la question suivante n'a pas été posée:

Alors, l'utilisation de ce nouveau modèle de programmation asynchrone présente-t-elle des inconvénients?

Le inconvénient qui est très minime (unité centrale/mémoire mineure autant que possible), c’est qu’il est possible que tout code soit exécuté après une instruction wait may exécuté sur thread séparé, une machine d'état existe pour stocker l'état du thread en cours d'exécution afin que la suite du travail puisse être gérée sur un autre thread. Vous pouvez en savoir plus sur la statemachine wait/async sur le blog de Dixin - Compréhension de C # async/wait (1) Compilation .

0
Erik Philips