WPF - WCF traitement asynchrone
-
mercredi 13 juin 2012 15:13Bonjour
voilà j'ai une application WPF qui se connecte a des services WCF...
J'ai la main sur le code du WCF et du WPF.
Pour mes traitements j'ai le choix entre :- des services synchrones avec un backgroundworker...
- des services asynchrones avec le traitement qui va avec...
Quelle méthodes pensez vous être la meilleurs ?
Auriez vous des tutos pour du WPF MVVM avec un écran du style "veuillez patienter !" pour les traitements ?
Merci de votre aide- Modifié CaptainChoc mercredi 13 juin 2012 15:13
Toutes les réponses
-
mercredi 13 juin 2012 17:50
Bonjour,
De manière générale, faire des appels en webservice de façon asynchrone est une bonne pratique il me semble, cela évite de geler l'affichage à cause d'une requete qui met trop de temps à arriver.
C'est aussi plus contraignant dans la mesure ou il faut gérer ces états temporaires ou on est en attente du resultat d'une requete.
Si ce sont des cas isolés ou si vous choisissez des proxies synchrones, le background worker est un des moyens possibles pour rendre certains appels asynchrones.
(un petit topic sur le sujet: http://stackoverflow.com/questions/5327096/is-backgroundworker-the-only-way-to-keep-a-wcf-wpf-application-responsive)
Petit avantage du BackgroundWorker ceci dit, c'est qu'il a un status (isBusy par exemple) qui peut etre utilisé directement dans la vue pour afficher un loader ou autres informationsIl me semble que si vous êtes sûr de vouloir faire tous vos appels en asynchrone, la meilleur solution consisterait à générer un proxy qui fait directement des appels asynchrones.
J'avais fait (il y a déjà un long moment...) un article sur une facon de packager les appels des webservices asynchrones qui a une pertinence relative mais qui peut donner des idées éventuellement:
http://charly-studio.com/blog/mvvmwcf-pattern-silverlight/Un autre article sur la msdn concernant les threading en WPF:
http://msdn.microsoft.com/en-us/library/ms741870.aspxen esperant vous avoir aidé dans vos recherches
Charles HETIER http://www.charly-studio.com
-
jeudi 14 juin 2012 07:33Modérateur
Bonjour,
Si vous êtes sous .NET Framework 4.0, vous pouvez aussi utiliser les Task pour déclencher un traintement asynchrone et une autre tâche qui s'exécute à fin de votre traitement afin de mettre à jour l'interface graphique.
C'est selon moi la solution la simple (en attendant les mots-clé async/await du 4.5) pour l'exécution de traitement asynchrone avec une interface graphique.
Cordialement
Gilles TOURREAU - MVP C#
Architecte logiciel/Consultant/Formateur Freelance
Blog : http://gilles.tourreau.fr
- MCPD : Enterprise Developper / Windows Developper 3.5 / ASP .NET 3.5/4.0
- MCITP : SQL Server 2008 Developper
- MCTS : ADO .NET 3.5 / SQL Server 2008 Developper / Windows Forms 3.5 / ASP .NET 3.5/4.0- Proposé comme réponse Pascal SailleModerator mardi 26 juin 2012 18:11
-
jeudi 14 juin 2012 09:45
Bonjour et merci de votre réponse,
J'aime bien l'idée d'utiliser les "Task" et ça convient bien au MVVM je pense. Dois je quand même générer mon proxy en asynchrone ? ou dois je utiliser les méthodes synchrones ?
De plus , pour mon interface, j'imaginais un UserControle qui s'affiche en plein milieu de l'écran lors d'un chargement (du style "Chargement en cours" et qui empêche les modifications à l'écran). L'affichage de ce UserControl serait "bindée" sur une variable static (par exemple Application.Current.IsBusy").
Et dans mon code, avant d'appeler mon service, je fais un "Application.Current.IsBusy = True" et une fois la réponse obtenue, je fais un "Application.Current.IsBusy = False".
Pensez vous que cette approche soit bonne ?
- Modifié CaptainChoc jeudi 14 juin 2012 09:46
-
dimanche 17 juin 2012 14:41Modérateur
Bonjour,
Si vous utilisez les tâches, préférez l'utilisation d'un proxy synchrone.
L'utilisation d'un proxy asynchronse (basé sur les événements) n'est pas si simple à coder. Et si vous devez exécuter une série d'opération synchrone sur votre webservice (tout en étant asynchrone au niveau de l'IHM), cela sera difficile à réaliser.Votre approche avec une propriété IsBusy est correct dans le cadre du pattern MVVM.
Cordialement
Gilles TOURREAU - MVP C#
Architecte logiciel/Consultant/Formateur Freelance
Blog : http://gilles.tourreau.fr
- MCPD : Enterprise Developper / Windows Developper 3.5 / ASP .NET 3.5/4.0
- MCITP : SQL Server 2008 Developper
- MCTS : ADO .NET 3.5 / SQL Server 2008 Developper / Windows Forms 3.5 / ASP .NET 3.5/4.0- Proposé comme réponse Pascal SailleModerator mardi 26 juin 2012 18:12
- Marqué comme réponse Gilles TOURREAUMVP, Moderator jeudi 19 juillet 2012 22:44
-
lundi 25 juin 2012 22:14Vous pouvez utiliser le pattern asynchrone généré pour les services WCF avec les Task. Il y a une méthode de Task qui est faite pour ca exactement (me souviens plus du nom de tête mais il attend le Beginxxx et le Endxxx comme arguments).
Richard Clark
Consultant - Formateur .NET
http://www.c2i.fr
Depuis 1996: le 1er site .NET francophone -
mardi 26 juin 2012 04:47Modérateur
Bonjour,
Est-ce que vous avez testé la solution proposée ? Merci de partager avec nous les résultats,afin que d'autres personnes avec le même problème puissent profiter de cette solution.
Cordialement, Pascal.
Développeur Wpf/SilverLight/WinPhone7
-
mardi 26 juin 2012 07:25
Bonjour,
j'ai finalement opté pour les Task du 4.0. avec des méthodes synchrones, très rapide à mettre en place.
this.IsBusy = true; Task saveTask = new Task(() => { this.Media = MediaService.Save(this.Media); }); saveTask.ContinueWith(t => { this.UpdateMedia(); this.IsBusy = false; }, CancellationToken.None, TaskContinuationOptions.NotOnFaulted, TaskScheduler.FromCurrentSynchronizationContext());
Cependant, j'ai un souci avec le "TaskScheduler.FromCurrentSynchronizationContext()" en effet si dans mon "UpdateMedia" je veux relancer une autre Task (qui va aussi mettre à jour l'UI), je ne peux utiliser "TaskScheduler.FromCurrentSynchronizationContext()" dans le "continueWith" de cette nouvelle Task. je dois passer alors utiliser "TaskScheduler.Current".
Mais si je veux appeler directement la méthode "UpdateMedia" (lors d'un clique sur un bouton par exemple), là je dois remettre "TaskScheduler.FromCurrentSynchronizationContext()".. il faut donc jongler avec le scheduler, ce que je trouve un peu lourd.
Je trouve qu'il manque une méthode du style "saveTask.Completed(t => { ...}) qui serai exécuter, lorsque la tache est terminée, dans le thread principal (à la maniere du OnRunWorkerCompleted du BackgroungWorker) pour si besoin relancer d'autre Task depuis le thread principal.
- Modifié CaptainChoc mardi 26 juin 2012 07:26
- Modifié CaptainChoc mardi 26 juin 2012 07:27
- Marqué comme réponse Gilles TOURREAUMVP, Moderator jeudi 19 juillet 2012 22:44

