2009-03-13 5 views
7

J'ai un appel asynchrone à la méthode de commande sqexexécutereader de sql, qu'un utilisateur peut annuler. Lorsque l'annulation se produit, j'annule l'objet sqlcommand, ce qui tue le travail en cours d'exécution sur le serveur sql.Détection de commande d'annulation dans asynchrone BeginExecuteReader

Cependant, dès que je l'annule, la méthode de rappel spécifiée dans la requête BeginExecute est appelée, et elle expire lorsque j'essaie d'appeler endexecutequery. Le result.Icompleted est vrai, jusqu'à ce que la requête endexecute soit appelée, à ce moment-là, elle devient false.

Est-il possible de détecter dans la méthode de rappel que la commande est annulée? ou dois-je garder une trace de cette ...

grâce

Répondre

8

J'ai effacé et remis en marche toute ma réponse: vous avez trébuché sur un bon cas de documents contradictoires et mises en garde ...

Selon le .NET 2.0 MSDN Documentation for the SqlCommand.Cancel « La méthode Cancel ne peut pas être utilisé pour annuler une asynchrone en attente opération." Cependant, la même documentation pour .NET 3.5 ne contient pas cet avertissement - bien qu'il soit identique à la documentation 2.0.

Je conseille de suivre les conventions décrites dans Calling Synchronous Methods Asynchronously qui est destiné à Delegate.BeginInvoke (pas Control.BeginInvoke!) Et Delegate.EndInvoke, mais est probablement pertinent dans votre cas.

Les méthodes nommées "Begin ... Async" qui renvoient un IAsyncResult et ont une méthode "End ..." correspondante ont le potentiel de créer une fuite ThreadPool. Le moyen le plus simple d'empêcher une fuite est de s'assurer que la méthode "End ..." correspondante est toujours appelée. La raison est que lorsque Begin ... Async est appelé, il reçoit un thread du ThreadPool et (typiquement) exécute la version synchrone de la méthode sur le thread de travail; dans votre cas, ExecuteReader(). La valeur de retour de cet appel, ou toute exception qui survient pendant cet appel, n'est pas ramenée au thread principal jusqu'à ce que End ... soit appelé - si vous n'appelez jamais End, les résultats/exceptions ne sont jamais retournés et le thread ThreadPool n'est jamais libéré. En bref, vous êtes probablement en sécurité tant que vous vous assurez d'appeler EndExecuteReader() et de gérer l'exception attendue. Depuis la documentation est contradictoire et vague, j'ai commencé un discussion on the MSDN Feedback Forums.

+0

J'ai essayé de comprendre comment annuler une opération SQL de longue durée de manière asynchrone, et c'est la seule réponse qui a fonctionné pour moi. Merci! – Porkbutts