10
votes

Quelle est la meilleure façon d'annuler une demande asynchrone de la WCF?

(en supposant une méthode de la WCF appelée "myfunction")

Actuellement, pour supporter l'annulation d'une demande de WCF, j'utilise les méthodes BegSmyFunction / EndMyFunction générées par SVCuttil (et gérant un drapeau iSCanceled lors de l'envoi des résultats sur le principal. fil). J'aimerais utiliser la méthode MyFunCunkaSync (et accrocher dans l'événement MyFunctionSyNCCompled à la place) pour les appels ASYNC au lieu de commencer / fin.

Quel est le moyen le mieux / pris en charge pour gérer l'annulation des demandes de WCF si vous utilisez myFunChUCTIONSYNCCompleted, tout en veillant à ce que l'événement ne soit pas tiré sur une page qui n'est plus chargée (c'est-à-dire la navigation de page dans un cadre).

merci!

EDIT:

J'ai décidé que je souhaite créer mon objet wcfclient sur une base par appel (par opposition à la page WPF ou par application par application), voici ce que j'ai proposé: xxx

Je trouve qu'il est difficile de comprendre quoi La façon recommandée d'accomplir ce que je viens de mettre en œuvre est. Est-ce que cette amende est-elle, ou y a-t-il des pièges / des cas de bord que je dois m'inquiéter? Quelle est la norme d'or lorsqu'il s'agit d'annuler correctement un appel WCF?


4 commentaires

De cette manière, vous n'ulsez pas vraiment de l'appel (c'est-à-dire qu'il fonctionne toujours à l'achèvement.) Vous vérifiez simplement si vous devez ignorer les résultats, non?


Très vrai. Cela garantit maintenant qu'au moins mon UI n'est pas mise à jour après la déchargement de la page. Je cherche dans quelle séquence d'appels que je devrais faire dans l'événement de déchargement (c'est-à-dire près, abandonner, etc.) pour contourner cette technique "signaleur" que j'utilise actuellement.


Calling Abort sur le déchargement n'annule pas toujours la demande (en fait, la demande est presque toujours terminée, Fiddler prouve que). J'ai ajouté un délai de 5 secondes sur le côté serveur pour me donner le temps d'abandonner l'appel. Ce n'est pas ce que j'attendrais.


Eh bien, je suppose qu'il n'est pas vraiment possible d'annuler une demande qui a déjà été envoyée au serveur. Comment feriez-vous cela? Courir après ça et lui dire de revenir? (Désolé, je n'ai pas pu résister ;-) Donc, à la fin de la journée, "Annuler" Les demandes de service Web ne se produisent que sur le calque d'applications. Je suppose que l'appel d'appel () ne fait rien de plus que d'ignorer la réponse en attente du serveur et libérant peut-être certaines ressources qui auraient été libérées plus tard autrement.


5 Réponses :


2
votes

L'annulation d'une demande n'est pas vraiment pratique dans le sens général simplement en raison de la nature asynchrone de la demande dont vous parlez. Les solutions de contournement spécifiques peuvent être effectuées. E.G., Ajout d'un nouveau signal d'annulation à votre protocole qui définit certains état partagé que votre tâche principale de longue date vérifie périodiquement pour vérifier qu'elle devrait continuer à exécuter.

De toute façon, à nouveau en raison de la nature asynchrone de la demande, je pense qu'il est toujours responsable de savoir que le client de savoir d'ignorer les résultats d'une demande annulée. Il n'est pas possible de garantir que le client ne recevra pas de réponse d'une demande qui vient d'être annulée simplement parce qu'une course existe entre le client et le serveur. Il est possible d'ajouter une couche supplémentaire qui surveille si quelque chose a été annulé et sait jeter la réponse d'une demande, mais cela n'empêche pas le résultat d'être transmis au client.


0 commentaires

7
votes

Il n'y a aucun moyen d'annuler la demande asynchrone à moins que vous ne créez manuellement les fonctions asynchrones. Considérant que vous générez automatiquement vos appels de WCF qui le feraient plus d'une corvée. Même comme vous avez dit que l'appel ne l'annule pas, cela fonctionnera toujours. Si vous souhaitez toujours avoir une annulation, il vous suffit de vous assurer que le client / UI ignore les résultats de l'appel.


0 commentaires

1
votes

Si je vous comprends correctement, vous essayez d'abandonner correctement un appel en attente à un service WCF. Vous souhaitez utiliser l'événement myFunctionCompletd car il est traité dans le fil de l'interface utilisateur.

Ce que vous devriez probablement faire est d'appeler la méthode abort sur le wcfclient < / code> (vous devez conserver une référence). Cela va nettoyer les ressources du côté du client. Le serveur devinera la demande, mais le client n'en attendra plus. Peu de temps après que l'événement MyFunctionPleted est déclenché. En cochant le client.state. / code> Vous saurez si l'appel a réussi, échoué ou a été abandonné.

Voici une petite application de test ayant un bouton d'envoi, un bouton d'avortement et une zone de texte pour les résultats: xxx

Il n'y a pas de manipulation et de nettoyage d'exception ... Je ne sais pas si c'est la voie recommandée, mais je pense que l'appelant Abort est le droit manière. Vous devez gérer les différentes situations d'erreur.


0 commentaires

4
votes

.NET 4.5

  1. Chaque implémentation de l'appel de la WCF crée une annulationTokenSource et la stocke dans un emplacement accessible à tous les services de la WCF. C'est à dire. Dans les environnements de serveur unique, vous pouvez être dans un cache en mémoire.
  2. Annellationtokensource.Token est transmis à tous les appels de méthodes initiés par la méthode WCF, y compris les appels vers des bases de données et des appels réseau, le cas échéant.
  3. La méthode WCF peut avoir un identifiant unique en tant que paramètre ou peut renvoyer un identifiant unique ce qui est associé à AnnellationTokenSource.
  4. Lorsque le client doit annuler l'opération appelle une méthode WCF et passe dans l'identifiant unique de l'appel précédent.
  5. CANCELLATIONTOKENSOURCE est récupéré à l'aide de l'identifiant unique et de sa méthode d'annulation est invoquée. Si le jeton d'annulation est traité correctement, l'opération lancée par un appel précédent sera bientôt annulée et peut renvoyer une opération de fonctionnementCanceledException ou un CANCONFAULON ou un autre défaut du client des signaux que l'appel a été annulé.
  6. Lorsque les appels de clients annuler à l'étape 4 peuvent en même temps, peut abandonner l'appel de WCF d'origine. Toutefois, si les clients gèrent correctement le fonctionnementCanceledException ou CANCELFAULT, ce n'est pas nécessaire. OperationCanceledException peut même buller jusqu'à un appel AJAX si l'appel original a été démarré à partir d'une page Web.

    Quelque chose de similaire peut être mis en œuvre dans les plus anciennes frameworks .NET où CancellationToken n'est pas encore disponible.


1 commentaires

Merci d'avoir répondu. Certaines références ou échantillons de code seraient super.



20
votes

La manière la plus simple que je connaisse de le faire avec un client WCF et le modèle Async basé sur la tâche consiste à enregistrer une action d'abandon avec le jeton d'annulation

private async Task CallOrAbortMyServiceAsync(CancellationToken cancellation)
{
    var client = new SomeServiceClient();
    cancellation.Register(() => client.Abort());
    try
    {
         await client.CallMyServiceAsync();
    } catch (CommunicationObjectAbortedException) {
          // This will be called when you are cancelled, or some other fault.
    }
}


1 commentaires

+1 belle mise en œuvre! Je recommanderais simplement l'élimination du résultat de annulation.register () , sinon l'enregistrement peut fuir.