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 :

Utilisation des tâches et interactions avec le thread principal


Sujet :

C#

  1. #1
    Membre régulier Avatar de windmastr26
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2009
    Messages
    234
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Juillet 2009
    Messages : 234
    Points : 108
    Points
    108
    Par défaut Utilisation des tâches et interactions avec le thread principal
    Bonjour,

    Je viens vers vous pour avoir des conseils sur l'utilisation des tâches en C#.

    Dans une appli où je dois faire du traitement de masse, j'ai une datagrid avec en première colonne une icône qui indique quel élément est en cours de traitement.

    Le mode opératoire souhaité est le suivant :
    1. Ma première ligne est traitée, mon icône prend la forme d'un gif animé de chargement,
    2. J'appelle ma tâche pour traiter mon enregistrement sans figer l'écran,
    3. Selon le résultat, la tâche doit mettre à jour la ligne (icône qui prend une forme différente selon le succès ou l'échec de la tâche),
    4. Passage à la ligne suivante.


    Je fais donc une boucle pour parcourir mon datagrid :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    for (int i = 0; i < datagrid.Rows.Count; i++) {
       [...]
       Task.Factory.StartNew(() =>
       {
          return matache(rowIndex, values);
       });
    }
    Et dans ma tâche, j'ai le code suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public async Task matache(int rowIndex, Dictionary<string, string> values)
    {
       [...]
       datagrid.BeginInvoke(new Action(() =>
       {
          ((DataGridViewImageCell)datagrid[0, rowIndex]).Value = Resources.monimage;
       }
    }
    En opérant comme ça j'ai plusieurs problèmes :
    • Les tâches ne s'exécutent pas les unes après les autres (je comprends pourquoi même si ça m'embête),
    • mon "rowIndex" dans ma tâche matache() se retrouve parfois avec une valeur hors limite car, de ce que je comprends, même si ma tâche est lancée, mon rowIndex continue à évoluer dans la boucle for()


    Que feriez-vous à ma place ? Quelles sont vos façons d'opérer ?

    Si vous avez des liens d'exemple ou du code dont je pourrais m'inspirer afin de maitriser ce système de tâche, ça me serait d'une grande aide !

    Merci pour vos retours

  2. #2
    Expert confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2009
    Messages
    2 025
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2009
    Messages : 2 025
    Points : 5 462
    Points
    5 462
    Par défaut
    Si tu veux que l'appelle de chaque row soit séquentiel alors je mettrais un await sur le task.factory.startnew (que je remplace par Task.Run, n'utilisant pas les autres paramètres du StartNew).
    Ma tache ne fera que le traitement et retourne le résultat. C'est ce résultat que j'interprete pour mettre à jour la row de la datagrid.

    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
     
    async [...](){
    [...]
     
    for (int i = 0; i < datagrid.Rows.Count; i++) {
       [...]
       await result=Task.Run(() =>
       {
          return matache(rowIndex, values);
       });
    if(result== OK)
    {
          ((DataGridViewImageCell)datagrid[0, rowIndex]).Value = Resources.monimage;
     
    }
     
    }
    J'ai pas le détail de matache, mais au lieux de passer "rowIndex", il vaut probablement mieux lui passer directement la/les valeurs que tu traites de manière à isoler complètement matache de tout aspect graphique.

  3. #3
    Membre régulier Avatar de windmastr26
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2009
    Messages
    234
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Juillet 2009
    Messages : 234
    Points : 108
    Points
    108
    Par défaut
    Merci Micka pour ton retour.

    J'avais testé cette solution :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Task<Task<bool>> task = (Task<Task<bool>>)Task.Factory.StartNew(() =>
    {
    	return matache(rowIndex, values);
    });
    task.Wait();
    bool bResult = task.Result.Result;
    if (bResult)
    {
       [...]
    }
     
    static public async Task<bool> matache(int rowIndex, Dictionary<string, string> values) {}
    Mais le problème, c'est que l'instruction ".Wait()" figeait le thread principal. Est-ce que je ne risque pas de rencontrer le même problème avec ton code ?

  4. #4
    Expert confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2009
    Messages
    2 025
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2009
    Messages : 2 025
    Points : 5 462
    Points
    5 462
    Par défaut
    Citation Envoyé par windmastr26 Voir le message
    Mais le problème, c'est que l'instruction ".Wait()" figeait le thread principal. Est-ce que je ne risque pas de rencontrer le même problème avec ton code ?
    Wait() va effectivement bloquer le thread appelant, c'est même son but.

    En revanche await est justement fait pour "rendre la main" et revenir lorsque le traitement est terminé.
    Il faut en revanche que la méthode dans lequel est ce bout de code soit elle même déclarée en async (ça le compilateur va te le dire), mais surtout il faut qu'elle soit appelée avec await (et ainsi de suite pour chaque méthode appelante).

    Si tu ne t'en sors pas, tu peux toujours utiliser ce bon vieux BackgroundWorker.

    https://webman.developpez.com/articl...ckroundworker/

  5. #5
    Membre régulier Avatar de windmastr26
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2009
    Messages
    234
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Juillet 2009
    Messages : 234
    Points : 108
    Points
    108
    Par défaut
    Merci encore pour ton retour Ça fonctionne à merveille et j'ai mieux compris certaines choses grâce à toi.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 13
    Dernier message: 18/07/2010, 18h10
  2. Utiliser des fonctions non objets avec Zend
    Par jux dans le forum Zend Framework
    Réponses: 6
    Dernier message: 08/02/2009, 11h58
  3. Utilisation des liste liées (ajax) avec du perl
    Par Jim_Nastiq dans le forum Web
    Réponses: 1
    Dernier message: 12/07/2006, 12h07
  4. Réponses: 2
    Dernier message: 08/07/2004, 01h04

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