Un désavantage de l'utilisation de ExecuteReaderAsync à partir de C# AsyncCTP
Il y a quelques articles qui indiquent que async appels de base de données sont une mauvaise idée .NET.
Sur C# Async CTP, il y a un System.Data.SqlClient.SqlCommand
extension 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 de ce genre sur mon code. Je suis donc d'avoir des pensées sur la conversion de ceux async.
Mais d'un autre côté, je ne vois pas beaucoup d'attraction sur cette approche là-bas (peut-être que je ne suis pas de chercher dans la bonne direction, qui sait!).
Alors, est-il à tous les inconvénients de l'utilisation de ce nouveau modèle de programmation asynchrone ici?
Edit:
En supposant que je refactoriser 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;
}
Aussi loin que je comprends bien le mot clé await, il convertit le code, qui est, après cela, que la continuation. Aussi, quand il frappe le mot clé await, il retourne immédiatement à son appelant, indépendamment de l'état de l'opération. Quand il a fini, il revient et de feu, la poursuite de code.
C'est ce que j'ai à l'esprit.
- Bien que l'on a accepté la réponse est parfait, je voudrais ajouter mon exemple. Dans mon site, j'ai fait toutes les méthodes d'action de la Tâche<ActionResult> et que toutes les db des appels asynchrones. Le site a vraiment commencé le chargement plus rapide
Vous devez vous connecter pour publier un commentaire.
Je suis en désaccord avec Ricka sur cette. Async DB commandes ne sont pas seulement bons, ils sont essentiels dans la réalisation de l'échelle, le débit et de latence. Son objection au sujet de la rampe jusqu'à l'heure du pool de threads s'applique uniquement à un serveur web que les expériences de faibles volumes de trafic.
Dans un trafic élevé de situation (qui est la seule qui compte), le pool de threads n'aurez pas à attendre pour "injecter" nouveaux threads. Faire les Commandes SQL de manière asynchrone est important, non seulement du point de vue de requêtes du serveur web/threads de la santé, mais aussi du point de vue de la demande totale à vie/temps de latence: non corrélés DB appels peuvent être effectuées en parallèle, plutôt que de façon séquentielle. Cette seules les résultats généralement à des améliorations spectaculaires dans la latence de la requête HTTP, telle que vécue par l'utilisateur. En d'autres termes, vos pages se chargent plus rapidement.
Un petit conseil cependant: Commande SQL n'est pas vraiment asynchrone jusqu'à ce que vous activez
Traitement Asynchrone=true
sur la chaîne de connexion. Alors que ce n'est pas définie (et par défaut n'est pas, Edit: en commençant avec .NET Framework < 4.5.Traitement Asynchrone
n'est plus nécessaire) votre "système" appels àBeginExecuteReader
ne sont rien, mais une imposture, l'appel va lancer un thread et de bloquer que fil. Lorsque la valeur est true async traitement est activé dans la chaîne de connexion l'appel est vraiment async et le rappel est basé sur IO achèvement.Un mot de prudence: un async commande SQL est à compléter dès que le première résultat renvoie au client, et les messages d'informations compter comme résultat.
Vous avez perdu tous les avantages de l'asynchrone. Le
print
crée un résultat qui est envoyé au client, qui vient compléter la async de commande et d'exécution sur le client reprend et se poursuit avec le lecteur.Read()'. Maintenant que bloquera jusqu'à ce que la requête complexe commencer à produire des résultats. Vous vous demandez " qui metprint
dans la procédure?' mais leprint
peut être déguisé en quelque chose d'autre, peut-être quelque chose d'aussi innocent à la recherche comme uneINSERT
qui exécute sans première émission d'uneSET NOCOUNT on
.ExecuteReaderAsync
n'est rien, mais un wrapper autour deBeginExecuteReader
/EndExecuteReader
, par conséquent, la chaîne de connexion exigence s'applique à lui aussi bien.SqlClient
composant. L'Async équipe est la construction de la langue et de la .Net Framework capacités à profit l'actuelIAsyncResult
fonctionnalités, pas à réinventer chacun à partir de zéro.public static Task<SqlDataReader> ExecuteReaderAsync(this SqlCommand source) { return Task<SqlDataReader>.Factory.FromAsync(new Func<AsyncCallback, object, IAsyncResult>(source.BeginExecuteReader), new Func<IAsyncResult, SqlDataReader>(source.EndExecuteReader), null); }
Je remarque que la question n'est pas abordée:
La inconvénient qui est très minime (mineur cpu/mémoire mineures autant que je sache), parce qu'il y a la possibilité de tout code exécuté après attendent une déclaration peut exécuter sur un thread séparé, une machine d'état existe pour stocker l'état du thread en cours d'exécution ainsi que la poursuite des travaux peuvent être traitées sur un autre thread. Vous pouvez en lire plus sur le attendent/async statemachine sur Dixin le Blog de la Compréhension de C# async /await (1) Compilation.