IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Bon usage Async Await


Sujet :

C#

  1. #1
    Membre émérite
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Points : 2 498
    Points
    2 498
    Par défaut Bon usage Async Await
    Bonjour
    Je me bat un peu pour intégrer le concept de async await et c'est pas encore tres clair
    Je pensais que le await permettait d'emuler une execution synchrone mais en test, ca semble tout l'inverse

    Pratiquement je veux lancer une tache asyncrone et traiter le resultat seulement quand c'est fini !

    Je bat encore de l'aile dans ce domaine mais ça va venir :-)
    Un conseil expert est bienvenu
    Merci !

    Exemple : (en commentaire le comportement souhaité et ce qui se passe réellement)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    28
    29
    30
    31
    32
    33
    34
    35
    Test()
        {
          CreateLogin(sLogin, Pwd);
          SetLoginInfo();
        }
        // *************************************************************************
        private  void CreateLogin(string Login,string Pwd)
        {
          var CreateLoginResult = CDB_ConseilleresExtended.CreateLoginAsync(curCons.ID.ToString(), Login, Pwd);
        }
    
       // ************************************************************
        public static async System.Threading.Tasks.Task<C_ErrorItem> CreateLoginAsync(string Code, string Email, string Pwd)
        {
    
          HttpClient client = new HttpClient();
          client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");
    
          Dictionary<string, string> Values = new Dictionary<string, string>();
          Values.Add("Email", Email);
          Values.Add("Password", Pwd);
          Values.Add("ConfirmPassword", Pwd);
          Values.Add("Code", Code);
    
          var content = new FormUrlEncodedContent(Values);
    
          var response = await client.PostAsync(MyUri, content);  // Inatendu : RETOUR DIRECT et execution de SetLoginInfo() 
    
          // Quand SetLoginInfo() a fini on retombe ici mais c'est tout a fait indesirable je devrais pouvoir appeller SetLoginInfo (ou un substitut) UNIQUEMENT quand PostAsync a fini !
    
    
          var responseString = await response.Content.ReadAsStringAsync();
    
          return new C_ErrorItem();
        }
    « Ils ne savaient pas que c'était impossible, alors ils l'ont fait ». (Twain)

  2. #2
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 654
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 654
    Points : 5 209
    Points
    5 209
    Par défaut
    C'est tout l'inverse !
    Async est fait pour réaliser des traitement en asynchrone...

    Si tu veux attendre la fin de la méthode lancée avec async, il faut utiliser await.
    Extrait de la documentation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    // Three things to note in the signature: 
    //  - The method has an async modifier.  
    //  - The return type is Task or Task<T>. (See "Return Types" section.)
    //    Here, it is Task<int> because the return statement returns an integer. 
    //  - The method name ends in "Async."
    async Task<int> AccessTheWebAsync()
    { 
        // You need to add a reference to System.Net.Http to declare client.
        HttpClient client = new HttpClient();
     
        // GetStringAsync returns a Task<string>. That means that when you await the 
        // task you'll get a string (urlContents).
        Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
     
        // You can do work here that doesn't rely on the string from GetStringAsync.
        DoIndependentWork();
     
        // The await operator suspends AccessTheWebAsync. 
        //  - AccessTheWebAsync can't continue until getStringTask is complete. 
        //  - Meanwhile, control returns to the caller of AccessTheWebAsync. 
        //  - Control resumes here when getStringTask is complete.  
        //  - The await operator then retrieves the string result from getStringTask. 
        string urlContents = await getStringTask;
     
        // The return statement specifies an integer result. 
        // Any methods that are awaiting AccessTheWebAsync retrieve the length value. 
        return urlContents.Length;

    Regarde cette page pour t'aider à comprendre :
    https://msdn.microsoft.com/fr-fr/lib...v=vs.120).aspx

  3. #3
    Membre émérite
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Points : 2 498
    Points
    2 498
    Par défaut
    Merci Popo

    Oui j'ai deja vu et revu ces doc mais ca ne m'a pas vraiment aidé a comprendre la bonne maniere de faire !
    Je dois avoir un cerveau qui ne capte pas bien les doc traditionnels

    Par rapport a mon exemple je vais continuer mes test en essai erreur, je finirai bien par comprendre

    Le but dans le cas présent est de pouvoir mettre a jour la Form quand la méthode asynchrone a fini son traitement !
    Actuellement c'est effectivement tout le contraire qui se passe ...

    Faut-définir un Call-back ?
    « Ils ne savaient pas que c'était impossible, alors ils l'ont fait ». (Twain)

  4. #4
    Membre émérite
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Points : 2 498
    Points
    2 498
    Par défaut
    Bonjour

    J'ai provisoirement résolu mon souci a la dure !

    Plutôt que de créer une méthode Async qui va elle même exécuter un PostAsync

    Je crée une méthode synchrone traditionnelle (qui remplace ma Methode CreateLoginAsync) et je force l'attente du retour du PostAsync avec .Result
    C'est évidemment pas comme ça que c'est censé être fait mais au moins ça me permet d'avancer !

    Mais je suis toujours curieux d'apprendre le design qui permettait d’exécuter en assync et d'intercepter le retour d’exécution afin de traiter a ce moment le résultat de cette exécution !

    Il me semble que peu de développeurs ont beaucoup d’expérience dans ce domaine



    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
        // ******************************************************************************************************
        public static C_ErrorItem CreateLogin(string Code, string Email, string Pwd)
        {
     
          HttpClient client = new HttpClient();
          client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");
     
          Dictionary<string, string> Values = new Dictionary<string, string>();
          Values.Add("Email", Email);
          Values.Add("Password", Pwd);
          Values.Add("ConfirmPassword", Pwd);
          Values.Add("Code", Code);
     
          var content = new FormUrlEncodedContent(Values);
     
          var response = client.PostAsync("https://espace.bemycloud.eu/api/Account/Register", content).Result;
     
     
          return new C_ErrorItem();
        }
    « Ils ne savaient pas que c'était impossible, alors ils l'ont fait ». (Twain)

  5. #5
    Membre émérite
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Points : 2 498
    Points
    2 498
    Par défaut
    Pour ceux que ca peut intéresser j'ai trouve un lien d'un blog de quelqu'un qui a fait un tres bel effort d'explication beaucoup plus clair que l'imbuvable MSDN



    https://blogs.infosupport.com/c-5-0-...e-as-possible/
    « Ils ne savaient pas que c'était impossible, alors ils l'ont fait ». (Twain)

  6. #6
    Membre chevronné
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 895
    Points : 1 911
    Points
    1 911
    Par défaut
    Le mot clé await va provoquer une sortie immédiate mais temporaire de la fonction en cours et permettre l'exécution du code qui suit son invocation, avant de revenir quand le résultat de la tâche lancée est arrivé. Pour avoir du code qui s'exécute après await, on peut le mettre dans la même fonction. Supposons que tu ais une fenêtre avec un bouton de connexion avec un événement clic (cas exemple d'une fenêtre WinForm) tu peux au choix utiliser un événement asynchrone, ou bien un événement synchrone mais qui appelle une méthode asynchrone afin de sortir immédiatement et ne pas bloquer l'UI.

    Exemple d'un événement asynchrone :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public async void ButtonConnect_Click(object sender, EventArgs e)
    {
    	try
    	{
    		// Dans le thread appelant : thread UI
    		var userInfos = await Task.Run(() => Connect(login, password)); // await fait temporairement sortir de la méthode
    		// retour dans le thread appelant au retour de la Task
    		LabelLogin.Text = userInfos.Login; // tout va bien, on est dans le thread UI
    	}
    	catch(Exception e)
    	{
    		LabelMessage.Text = e.Message;
    	}
    }
    Avec un événement synchrone qui appelle une méthode asynchrone :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    public void ButtonConnect_Click(object sender, EventArgs e)
    {
    	ConnectAndDisplayAsync();
    }
     
    public async Task ConnectAndDisplayAsync()
    {
    	try
    	{
    		// Dans le thread appelant : thread UI
    		var userInfos = await Task.Run(() => Connect(login, password)); // await fait temporairement sortir de la méthode
    		// retour dans le thread appelant au retour de la Task
    		LabelLogin.Text = userInfos.Login; // tout va bien, on est dans le thread UI
    	}
    	catch(Exception e)
    	{
    		LabelMessage.Text = e.Message;
    	}
    }
    La signature de la méthode hypothétique Connect, pour référence :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public UserInfos Connect(string login, string password){ ... }
    Tu peux jeter une œil sur le tutoriel de François Dorin sur l'utilisation du pool de threads, la partie 3 concernant justement le couple async/await.

Discussions similaires

  1. du bon usage de ONCLICK
    Par devboy dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 15/05/2007, 16h52
  2. Bon Usage : Constructeur ou Load
    Par gridin dans le forum VB.NET
    Réponses: 1
    Dernier message: 10/05/2007, 08h48
  3. [Delphi - Firebird] Comment faire bon usage des transactions?
    Par Lili21 dans le forum Connexion aux bases de données
    Réponses: 2
    Dernier message: 07/05/2007, 21h59
  4. Quel est le bon usage des fichiers "*.bpk" ?!
    Par bnadem35 dans le forum C++Builder
    Réponses: 3
    Dernier message: 12/09/2006, 18h31
  5. [xml] bon usage du xml
    Par Jeddo dans le forum XML/XSL et SOAP
    Réponses: 8
    Dernier message: 02/05/2005, 17h49

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo