Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Utilisez-vous le nouveau modèle de programmation asynchrone de C# 5/VB 11 ?
Qu'en pensez-vous ? Participez au débat et partagez votre expérience

Le , par tomlev

22PARTAGES

6  2 
Utilisez-vous le nouveau modèle de programmation asynchrone de C# 5/VB 11 ?


Utilisez-vous le nouveau modèle de programmation asynchrone de C# 5/VB 11 ?


Comme vous le savez sans doute, la version 5 de C# (comme la version 11 de VB.NET) a introduit de nouveaux mots-clés pour faciliter l'écriture de code asynchrone : async et await. Ce nouveau modèle permet d'écrire très simplement du code qui ne bloque pas l'UI et ne monopolise pas inutilement des threads de travail.

Une introduction à la programmation asynchrone en C# 5, par Eric Lippert

Par exemple, pour télécharger des données depuis le web :

  • code synchrone (bloque l'UI pendant l'exécution de la requête) :

    Code C# : Sélectionner tout
    1
    2
    3
    4
    5
    6
    private void btnDownload_Click(object sender, EventArgs e) 
    { 
        var client = new WebClient(); 
        string data = client.DownloadString("http://monserveur.com/data"); 
        txtData.Text = data; 
    }
  • code asynchrone « classique » :

    Code C# : Sélectionner tout
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    private void btnDownload_Click(object sender, EventArgs e) 
    { 
        var client = new WebClient(); 
        client.DownloadStringCompleted += client_DownloadStringCompleted; 
        client.DownloadStringAsync("http://monserveur.com/data"); 
    } 
      
    private void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) 
    { 
        txtData.Text = e.Result; 
    }

    Ce code est nettement moins lisible ; le déclenchement de la requête est séparé de la récupération du résultat, ce qui rend le déroulement plus difficile à suivre.
  • code asynchrone C# 5 :

    Code C# : Sélectionner tout
    1
    2
    3
    4
    5
    6
    private async void btnDownload_Click(object sender, EventArgs e) 
    { 
        var client = new WebClient(); 
        string data = await client.DownloadStringTaskAsync("http://monserveur.com/data"); 
        txtData.Text = data; 
    }

    On remarque que ce code est quasiment identique au code synchrone de départ ; on l'a rendu asynchrone, sans rien sacrifier à la lisibilité.


Microsoft pousse de plus en plus à l'utilisation de ce modèle, notamment sur Windows Phone 8 et dans les applications Windows Store (Metro) ; bien souvent, seules des API asynchrones sont proposées, et les API synchrones habituelles sont supprimées si elles existaient.

Pourtant, il me semble qu'on voit assez peu de discussions qui abordent ce sujet sur les forums, ce qui me pousse à ouvrir ce débat…

Et vous ?

Utilisez-vous le nouveau modèle de programmation asynchrone ? En C# ou en VB.NET ? Sur quelle plateforme (bureau, Windows Phone, WinRT, ASP.NET…) ?
Si non, pourquoi ? Éprouvez-vous des difficultés à comprendre son fonctionnement ?
Si oui, qu'en pensez-vous ? Comment a-t-il changé votre façon de programmer ? Quelles difficultés avez-vous rencontrées lors de son utilisation ?

À lire aussi :

Quel est votre langage de programmation préféré en 2013 ?

Quel est votre environnement de développement (EDI) préféré en 2013 ?

Une erreur dans cette actualité ? Signalez-le nous !

Avatar de tomlev
Rédacteur/Modérateur https://www.developpez.com
Le 31/07/2013 à 14:10
Bon, je me lance...

Utilisez-vous le nouveau modèle de programmation asynchrone ? En C# ou en VB.NET ? Sur quelle plateforme (bureau, Windows Phone, WinRT, ASP.NET…) ?
Je l'utilise sur la plupart de mes projets récents, principalement pour des applis Windows Store (WinRT), mais aussi pour des applis bureau.

Détail intéressant : il n'est pas forcément nécessaire de cibler .NET 4.5 ou Windows Phone 8 pour pouvoir utiliser async/await. A condition d'utiliser VS2012 (et donc le compilateur C# 5) et d'ajouter le package Nuget Microsoft.Bcl.Async, on peut également cibler également des environnements plus anciens, comme .NET 4, Silverlight 4 ou Windows Phone 7.5

Si oui, qu'en pensez-vous ? Comment a-t-il changé votre façon de programmer ? Quelles difficultés avez-vous rencontrées lors de son utilisation ?
Personnellement je suis plutôt convaincu par le modèle async/await. Ça rend la programmation asynchrone tellement facile qu'on en fait sans même y penser, alors qu'avant beaucoup de traitements étaient faits en synchrone par simple flemme, parce que les faire de façon asynchrone était trop "prise de tête".

Par contre il y a un effet pervers : le code asynchrone est assez "contagieux". Il est difficile de faire une partie des traitements en asynchrone sans que ça "envahisse" un peu le reste du code. En effet, dès qu'on appelle une méthode asynchrone :
  • soit on "await" le résultat et dans ce cas on devient donc asynchrone aussi
  • soit on bloque en attendant le résultat, mais dans ce cas on perd l'avantage de l'appel asynchrone
  • soit on fait du "fire and forget", c'est à dire qu'on lance l'opération asynchrone sans se soucier de son résultat

On peut donc se retrouver assez vite avec du code asynchrone à tous les niveaux du code, y compris à des endroits où ça ne semblait pas nécessaire a priori

Sinon, au niveau des difficultés, il y a pas mal de situations où on ne peut pas utiliser de code asynchrone, tout simplement parce que le langage n'avait pas été prévu pour ça au départ : constructeurs, propriétés, évènements, blocs catch et finally, etc. Ça oblige souvent à faire des trucs bizarres pour arriver au résultat voulu.
(voir cette série d'articles sur le sujet: http://blog.stephencleary.com/search...el/async%20oop)

D'autre part, j'ai l'impression qu'il y a une idée reçue assez répandue selon laquelle le code asynchrone implique forcément l'utilisation de plusieurs threads. Mais ce n'est absolument pas vrai dans le cas général ; certains traitements asynchrones vont effectivement s'exécuter sur un autre thread, mais bien souvent ce n'est pas nécessaire. Par exemple les opérations d'entrée/sortie asynchrone n'utilisent pas de thread de travail : la partie "attente" n'implique pas du tout le processeur, c'est un IO Completion Port qui va notifier la fin de la tâche. D'ailleurs on peut facilement trouver des scénarios asynchrones qui n'ont absolument rien à voir avec les threads ; par exemple ce code attend (sans bloquer) que l'utilisateur clique sur un bouton :

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
async void Test()
{
    await button.WaitForClickAsync();
    MessageBox.Show("Hello");
}

public static class ButtonExtensions
{
    public static Task WaitForClickAsync(this Button button, CancellationToken cancellationToken = default(CancellationToken))
    {
		var tcs = new TaskCompletionSource<object>();
                EventHandler handler = null;
		handler = (sender, e) =>
		{
			button.Click -= handler;
			tcs.TrySetResult(null);
		};
		cancellationToken.Register(() =>
		{
			button.Click -= handler;
			tcs.TrySetCanceled();
		});
		
		button.Click += handler;
		return tcs.Task;
    }
}
3  0 
Avatar de tomlev
Rédacteur/Modérateur https://www.developpez.com
Le 08/08/2013 à 14:37
Citation Envoyé par transgohan Voir le message
Dans l'exemple fourni avec await, comment sait-on que txtData.Text a été mis à jour à la suite du traitement asynchrone ?
C'est-à-dire ? Je ne comprends pas ta question. Quand l'appel asynchrone à DownloadStringTaskAsync se termine, la fonction reprend là où elle s'était interrompue, et exécute le txtData.Text = data;.

Citation Envoyé par transgohan Voir le message
Et je vois surtout une saleté dans ce code, c'est un piège pour tous les débutants qui vont croire à un code synchrone à la première lecture et s'embourber jusqu'à trouver leur connerie (le petit await qu'ils avaient lu en diagonale)... (et là ça peut durer longtemps !)
Bah oui mais bon, si tu fais pas attention au code que tu lis, évidemment ça pose des problèmes... Tu ne peux pas dire qu'une feature est mauvaise juste parce qu'elle risque de poser des problèmes aux débutants.
3  0 
Avatar de erwanlb
Inactif https://www.developpez.com
Le 08/08/2013 à 14:47
Citation Envoyé par transgohan Voir le message
Je bosse pas sur cette technologie mais en lisant ça j'essaie de comprendre.
Cela ne me paraît pas tiptop, mais je peux me tromper sans avoir les bons éléments d'explication.

Dans l'exemple fourni avec await, comment sait-on que txtData.Text a été mis à jour à la suite du traitement asynchrone ?
Et je vois surtout une saleté dans ce code, c'est un piège pour tous les débutants qui vont croire à un code synchrone à la première lecture et s'embourber jusqu'à trouver leur connerie (le petit await qu'ils avaient lu en diagonale)... (et là ça peut durer longtemps !)
Vu la première question, tu serais le débutant en question....et tu vois tu as bien vu le await

Si maintenant il faut prévenir les débutants de lire un code en entier, où est ce qu'on va............
3  0 
Avatar de Gugelhupf
Modérateur https://www.developpez.com
Le 08/08/2013 à 19:44
Bonsoir,

N'aurait-t-il pas été possible de faire :
Code : Sélectionner tout
1
2
3
4
5
6
7
8
private void btnDownload_Click(object sender, EventArgs e)
{
    new Thread(() => {
        var client = new WebClient();
        string data = client.DownloadString("http://monserveur.com/data");
        txtData.Text = data;
    }).Start();
}
Ou bien est-ce que c'est interdit/déconseillé ?

Merci.
2  0 
Avatar de atha2
Membre éprouvé https://www.developpez.com
Le 09/08/2013 à 1:03
Citation Envoyé par tomlev Voir le message
C'est possible, mais ça présente plusieurs inconvénients :
  • C'est nettement plus lourd en terme de syntaxe

C'est une question de point de vue. Même si c'est plus long à écrire, la syntaxe de Gugelhupf montre ce qu'on fait et n'importe quel développeur comprend le code. Je suis développeur Java et je suis régulièrement amené à travailler sur des développements C#. Sans cet article, je n'aurai probablement mal compris ce code et perdu pas mal de temps à le débugger.

Citation Envoyé par tomlev Voir le message


  • Télécharger des données est intrinsèquement une tâche d'entrée/sortie, il n'est donc pas utile de monopoliser un thread pour le faire. Ce thread passera l'essentiel de son temps bloqué à attendre que le téléchargement se termine...

Il y a probablement quand même un thread qui gère les I/O en background et va prévenir le thread graphique qu'il faut reprendre l’exécution de la fonction. Même si celui nous est masqué et est géré par .NET.
Citation Envoyé par tomlev Voir le message


  • En l'état, ça ne fonctionnera pas, parce que txtData.Text = data; ne peut être exécuté que sur le thread de l'UI. Modifier l'UI depuis un autre thread provoquera une exception. Pour contourner ce problème, il faudrait passer par la méthode Invoke pour exécuter ce code sur le thread de l'UI, ce qui alourdirait encore plus l'ensemble.

Il existe une méthode, dont le nom m'échappe, qui permet, en une instruction, de mettre à jour un composant graphique (qui doit utiliser Invoke en interne). La syntaxe doit ressembler à quelque chose comme ça :
Code : Sélectionner tout
updateInUIThread(txtData, "Text", data);

Au final, sur ce que j'en vois, le modèle async/await est surement très pratique une fois bien maitrisée. Mais j'ai du mal avec le mot clé "async" alors que le début de la méthode (avant le await) est exécuté de façon synchrone
2  0 
Avatar de Guulh
Membre émérite https://www.developpez.com
Le 09/08/2013 à 10:06
Citation Envoyé par atha2 Voir le message
C'est une question de point de vue. Même si c'est plus long à écrire, la syntaxe de Gugelhupf montre ce qu'on fait et n'importe quel développeur comprend le code. Je suis développeur Java et je suis régulièrement amené à travailler sur des développements C#. Sans cet article, je n'aurai probablement mal compris ce code et perdu pas mal de temps à le débugger.
Donc pour suivre la même logique, il faut se passer de Linq parce que seul .Net l'a, il faut se passer de WPF, WCF pour la même raison, ne pas faire d'objet pour ne pas dérouter ceux qui font du C...
Les langages rajoutent du sucre au fur et à mesure. Leurs concepteurs détectent des patterns très fréquents, et proposent des syntaxes simplifiées, ce qui minimise les risques de bug (pas de IndexOutOfRangeException avec un foreach!) et uniformise le code, ce qui en facilite la maintenance.
Pour l'instant, j'ai l'impression que Microsoft a réussi à faire utiliser toutes les features qu'ils ont ajoutées (même si je n'ai pas encore beaucoup vu d'usages de in/out pour la co-Contravariance, ou de dynamic pour le dispatch dynamique), pqrce au'elles correspondaient à un besoin réel et pragamatique.

Après, comme tout nouvel outil, je suis curieux de voir comment il sera mal utilisé: est-ce qu'il sera abusé par des gasr qui veulent trop bien faire ou qui ont rien capté Surveillons thedailywtf.com pour le savoir
3  1 
Avatar de jmnicolas
Membre éprouvé https://www.developpez.com
Le 08/08/2013 à 15:36
Je n'utilise pas : je suis en .NET 4 avec VS 2010.
On a encore plein de machines sous XP / 2003 Server, et .NET 4 et la dernière version qui tourne dessus.
1  0 
Avatar de tomlev
Rédacteur/Modérateur https://www.developpez.com
Le 08/08/2013 à 16:46
Citation Envoyé par transgohan Voir le message
Je trouve pas cela très intuitif mais ce n'est que mon avis.
A mon avis tu trouves ça pas intuitif parce que tu t'es habitué au fait que le code asynchrone ne soit pas intuitif . L'avantage de ce nouveau modèle, c'est justement que le code asynchrone devient aussi intuitif que le code synchrone (du moins une fois que tu as compris le principe)
1  0 
Avatar de yoyo88
Membre chevronné https://www.developpez.com
Le 08/08/2013 à 17:17
j'ai voté non bien que j'ai déjà travailler avec ceci notamment pour essayer winRT. mais c'était a titre purement perso.

sur l'un de mes tous premiers projet sur winRT j'ai utiliser ça sans trop savoir comment ça fonctionnais.
Et c'est vrai qu'on prend vite le coup.

Apres je mettrai un bémol, puisque du coup il faut pensez qu'une méthode "async" bien qu'aillant exactement la tête d'une méthode synchrone ne l'ai pas.

c'est con , mais j'ai tellement pris l'habitude de lancer un appel asynchrone par une méthode et de revenir par une autre que du coup cela semble illogique de procéder ainsi.

Je pense, que du coup,il faut bien mettre en évidence le faite que la méthode est asynchrone (commentaire / region ? ).

je n'ai pas assez utiliser pour avoir un avis trancher, mais de se que j'ai essayer c'est quand même pas mal.
Apres, j'ai remarqué que quand on commence les async/await, on en fou partout dans le code, chose qui auparavant n'était pas le cas avec des fonction asynchrone classique. (après c'est peu être parce que je n'avais pas bien saisie le concept au moment ou j'ai essayer...)
1  0 
Avatar de GTSLASH
Inactif https://www.developpez.com
Le 08/08/2013 à 18:08
Pour faire simple on peut dire je pense que l'appel a une ou plusieurs tache peut se faire dans la methode en cours sans bloquer le Thread de l'interface utilisateur.

Sans le systeme 'await' le thread de l'UI resterait bloqué jusqua ce qu'il ait recu la reponse.

C'est le principal atout je trouve. Plus besoin d'utiliser un BusyIndicator ou autre pour empecher l'utilisateur d'utiliser l'UI. car un beau 'Pas de reponse' apparaitrai si il utiliserai le thread d'affichage. Et ce sans avoir besoin de passer par la tuyauterie d'un BackgroundWorker qui demande beaucoup plus de code.

Et avec les processeurs multi-coeur actuel il etait temp d'avoir les outils et framework nous permetant de les utilisés pleinements.
1  0