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 :

Task vs BeginInvoke


Sujet :

C#

  1. #1
    Membre actif
    Homme Profil pro
    Architecte technique
    Inscrit en
    février 2004
    Messages
    468
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Service public

    Informations forums :
    Inscription : février 2004
    Messages : 468
    Points : 220
    Points
    220
    Par défaut Task vs BeginInvoke
    Bonjour à tous,

    Aujourd'hui nous utilisons beginInvoke pour charger nos données depuis la base de données en asynchrone.
    Cela permet de ne pas freezer nos applications Winform et de lancer des events du back vers le front (GUI) pour gérer l'affichage d'une barre de progression.

    On se pose la question d'utiliser le pattern async / await.

    Cependant je me rends compte que si j'utilise des méthodes "async", tout devient "async" pour les utiliser.

    Est ce que vous confirmez ?
    Notamment un event de type private void btSearch_Click(object sender, EventArgs e) devra être réécrit private async void btSearch_Click(object sender, EventArgs e).

    Ensuite j'ai cette tâche asynchrone "getAsync", qui appelle la méthode "get", et dans la méthode get j'appelle une méthode synchrone "getListBo".

    Visiblement malgré le fait que la tâche soit marquée "async" elle se bloque sur la méthode synchrone.
    Est-ce normal ?

    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
    // - Méthode asynchrone basée sur BeginInvoke
    public void beginGetClients(IGTMFilter gtmClientFilter)
            {          
                    // -- Création du délégué et lancement de la
                    // -- méthode synchrone
                    // ------------------------------------------
                    getClientsDelegate getClientsDlg = new getClientsDelegate(get);
                    getClientsDlg.BeginInvoke(gtmClientFilter, null, null);            
            }
     
    // -- Tâche asynchrone basée sur le patter async / await
    public async Task getAsync(IGTMFilter filter, TaskScheduler uiScheduler, CancellationTokenSource cancellationTokenSrc)
            {     
                await Task.Factory.StartNew(
                     () => get(filter),
                     cancellationTokenSrc == null ? CancellationToken.None : cancellationTokenSrc.Token,
                     TaskCreationOptions.None, uiScheduler);
            }
     
    // -- Méthode synchrone
    protected override List<Client> get(IFilter Filter, DbConnection dbConnection)
          {
                    // -- Initialisation de la liste des clients
                    // -----------------------------------------
                    return getListBO(selectQuery);
          }

  2. #2
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    juin 2022
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : juin 2022
    Messages : 11
    Points : 18
    Points
    18
    Par défaut
    Bonjour,

    Vous avez englobé votre méthode synchrone et longue (car elle interroge une ressource externe) dans une tache asynchrone, mais l’utilisation du mot clé await entraine un blocage en attendant la réponse de votre base de données, du coup vous vous retrouvez dans la même situation : vous êtes dépendant de la durée de votre requête.

    Du moins après votre appel à getAsync, votre code devrait continuer et votre tâche continuer à traiter la requête en parallèle.
    Une fois votre requête terminée vous pouvez récupérer le résultat de la tâche.

    Par contre si vous attendez le résultat de la tache immédiatement, ce qui a l’air d’être fait ici, le code attend le résultat et bloque.

    Voilà un exemple de ce que j’essaie d’illustrer :

    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
     
                Console.WriteLine("Démarrage ...");
     
                var test = Task.Run<string>(() => 
                {
                    Console.WriteLine("Ma tache");
                    Thread.Sleep(5000);
                    return File.ReadAllText(@"c:\temp\test.txt"); 
                });
     
                Console.WriteLine("Mon code continue ...");
     
                Thread.Sleep(5000);
     
                Console.WriteLine($"Mon résultat : {test.Result}");
     
                Console.WriteLine("Fin");
     
                Console.ReadLine();
    Ici la tâche va s’exécuter mais pas bloquer la suite du programme, par contre au moment où vous aller demander à récupérer le résultat, si !

    Je ne peux pas trop vous aider sans avoir un contexte plus global, mais en espérant avoir aidé un peu.

    Sinon au lieu de vous compliquer la vie, vous pouvez rester sur l'exécution d'un thread pour la lecture en base qui lève un évènement de fin avec les résultats.

    Cordialement.

  3. #3
    Expert éminent sénior

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    juillet 2016
    Messages
    2 678
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : juillet 2016
    Messages : 2 678
    Points : 10 460
    Points
    10 460
    Billets dans le blog
    21
    Par défaut
    Citation Envoyé par Pfeffer Voir le message
    Cependant je me rends compte que si j'utilise des méthodes "async", tout devient "async" pour les utiliser.

    Est ce que vous confirmez ?
    Non, tout ne devient pas forcément async. Une méthode async, du point de vue de l'appelant, est juste une méthode renvoyant une Task. Une méthode renvoyant une Task sans utilisation du mot clé async peut même être employée avec le mot clé await.

    L'avantage d'utiliser async/await, c'est que le code synchrone et asynchrone sont identiques, à l'insertion des mots clés près. Mais si cette propagation est "douloureuse", il est tout à fait possible de changer un peu l'organisation du code pour s'en passer (mais cela demande une petite refactorisation pour transformer du code synchrone en code asynchrone).

    Quand on a une Task, on peut faire plusieurs choses, notamment :
    • la lancée et l'ignorée totalement ensuite
    • l'attendre avec Task.Wait() ou await, ou récupérer la valeur de retour de la tâche via Task.Result (qui attend implicitement la fin de la tâche)
    • chaîner des actions à exécuter après (par exemple, avec Task.ContinueWit()


    Mixer les wait/Task.Wait dans un code est plutôt déconseillé, surtout dans des codes à exécution monothread (comme pour les Winforms) pour éviter des blocages pur et simple.
    François DORIN
    Consultant informatique : conception, modélisation, développement (C#/.Net et SQL Server)
    Site internet | Profils Viadéo & LinkedIn
    ---------
    Page de cours : fdorin.developpez.com
    ---------
    N'oubliez pas de consulter la FAQ C# ainsi que les cours et tutoriels

Discussions similaires

  1. [ant] jar task ajout de librairie
    Par noOneIsInnocent dans le forum ANT
    Réponses: 4
    Dernier message: 14/04/2006, 17h11
  2. [ant] jar task
    Par noOneIsInnocent dans le forum ANT
    Réponses: 4
    Dernier message: 13/04/2006, 17h04
  3. [Task] Lancer un programme à une date donnée ?
    Par jsl1 dans le forum API standards et tierces
    Réponses: 3
    Dernier message: 27/01/2006, 12h44
  4. Scheduled Task
    Par wiglaft dans le forum API, COM et SDKs
    Réponses: 1
    Dernier message: 22/12/2005, 04h49
  5. Réponses: 4
    Dernier message: 14/01/2005, 19h41

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