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 :

Backgroundworker et taches qui suivent


Sujet :

C#

  1. #1
    Membre chevronné Avatar de petitours
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Février 2003
    Messages
    1 935
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 935
    Points : 2 013
    Points
    2 013
    Par défaut Backgroundworker et taches qui suivent
    Bonjour

    Quand on a dans son code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Des choses()
    LancementBackGroundWorker();
    TachesSuite1();
    TachesSuite2();
    TachesSuites1 et 2 sont sensées s'exécuter
    1)-dés que le backgroundworker est lancé ?
    2)-une fois le backgroundworker est terminé ?

    Je pose la question par ce qu'il semblerait que ca me fasse le 2) là... mais le 1) me parait pourtant plus logique...

    Merci
    Il y a 10 sortes de personnes dans le monde : ceux qui comprennent le binaire et les autres

  2. #2
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Points : 2 605
    Points
    2 605
    Par défaut
    Bonjour.

    Le lancement d'un backgroundworker déclenche un thread qui va s'exécuter en même temps que tout le reste.

    Je vois trois possibilités donc :

    - TachesSuite1 s'exécute avant le thread du backgroundworker. Je ne confirmerai pas, mais c'est une possibilité. Il faudrait scruter les détails de cettte API.

    - TachesSuite1 s'exécute après la fin du backgroundworker. Il est possible que le backgroundworker se termine avant, parce qu'il ne nécessite que très peu d'instructions processeurs (- de 20 millisecondes par exemple).

    - Le cas le plus probable, le backgroundworker s'exécute en même temps que TachesSuite1.

    Si le programme n'a pas de mécanisme d'attente et que l'on exécute plusieurs fois le pseudo code ci-dessus, la possibilité que ce soit toujours le cas 1, 2 ou 3 est impossible à prévoir.

    Il faut aussi prendre en compte la priorité des threads.

  3. #3
    Membre chevronné Avatar de petitours
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Février 2003
    Messages
    1 935
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 935
    Points : 2 013
    Points
    2 013
    Par défaut
    Bonjour

    Et ben je n'y comprends plus rien

    dans mon cas j'ai
    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
    EnvoiOrdre(MonOrdre); //envoi d'un ordre à la carte électronique
    backgroundWorkerOrdre.RunWorkerAsync(thisClass); //attente accusé reception de la carte, ça prend 2  secondes environ, le résultat va dans byte InBuffer[]
    if (InBuffer[0] == ACK)
    {
    toolStripStatusLabel1.Text = Titre + " : " + MessageReussite;
    }
    else if (InBuffer[0] == NAK)
    {
     toolStripStatusLabel1.Text = Titre + " : " + MessageEchec;
    }
    else if (InBuffer[0] == INCONNU)
    {
    toolStripStatusLabel1.Text = "La carte n'a pas reconnu l'ordre envoyé !!!!!!!!";
    }
    else 
    {
    toolStripStatusLabel1.Text = "Accusé réception retourné par la carte inconnu !!";
    }
    et ce que je ne comprends pas c'est que j'ai bien le message de réussite qui apparait au bout des deux secondes ! Comme si le test de InBuffer avait attendu la fin de l’exécution du backgroundworker !

    Comment est ce possible ?

    Merci
    Il y a 10 sortes de personnes dans le monde : ceux qui comprennent le binaire et les autres

  4. #4
    Membre expérimenté
    Homme Profil pro
    Développeur .Net / Delphi
    Inscrit en
    Juillet 2002
    Messages
    738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Eure (Haute Normandie)

    Informations professionnelles :
    Activité : Développeur .Net / Delphi
    Secteur : Finance

    Informations forums :
    Inscription : Juillet 2002
    Messages : 738
    Points : 1 745
    Points
    1 745
    Par défaut
    Bonjour,

    Est-ce que la variable de réception n'était pas déjà renseignée suite à la demande précédente ?
    Le BackGroundWorker n'est pas synchrone (heureusement, il ne servirait à rien sinon). Donc ...

    Théoriquement, il faudrait tester le retour dans l'évènement RunWorkerCompleted du BackgroundWorker.

    eb

  5. #5
    Membre chevronné Avatar de petitours
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Février 2003
    Messages
    1 935
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 935
    Points : 2 013
    Points
    2 013
    Par défaut
    Bonjour

    Oui, la variable de réception est à priori forcément renseignée du coup d'avant.
    Mais ca devrait s'exécuter immédiatement, là les affichages
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    toolStripStatusLabel1.Text = Titre + " : " + MessageReussite;
    apparaissent au bout des 2s, comme si c'était après la fin d’exécution du backgroundworker.

    Je tente un bout de programme tout simple à base de backgroundworker pour mieux comprendre là...
    Il y a 10 sortes de personnes dans le monde : ceux qui comprennent le binaire et les autres

  6. #6
    Membre chevronné Avatar de petitours
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Février 2003
    Messages
    1 935
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 935
    Points : 2 013
    Points
    2 013
    Par défaut
    Bon j'ai fait un petit exemple avec une tache de fond qui fait avancer un progressBar, bouton annulé et tout, je comprends mieux.

    Très clairement il faut que je mette mes traitements dans l'évènement RunWorkerCompleted, sinon ça n'a pas de sens.

    Problème : Je dois utiliser dans l'évènement RunWorkerCompleted des string que je connais dans la fonction qui lance le backgroundworker.
    Je sais les passer à travers les arguments (via une classe) à la fonction DoWork mais comment avoir ces chaines encore disponibles dans l'évènement final ?

    Merci
    Il y a 10 sortes de personnes dans le monde : ceux qui comprennent le binaire et les autres

  7. #7
    Membre expérimenté
    Homme Profil pro
    Développeur .Net / Delphi
    Inscrit en
    Juillet 2002
    Messages
    738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Eure (Haute Normandie)

    Informations professionnelles :
    Activité : Développeur .Net / Delphi
    Secteur : Finance

    Informations forums :
    Inscription : Juillet 2002
    Messages : 738
    Points : 1 745
    Points
    1 745
    Par défaut
    Bonjour,
    Tu peux assigner le résultat de ton traitement dans e.Result au niveau du DoWork. L'évènement RunWorkerCompleted fournit cette propriété en argument.

    Msdn

    eb.

  8. #8
    Membre chevronné Avatar de petitours
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Février 2003
    Messages
    1 935
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 935
    Points : 2 013
    Points
    2 013
    Par défaut
    Super, j'ai trouvé comment faire, c'était aussi simple que pour passer les arguments au DoWork... Ca fonctionne bien quand la tache se déroule normalement.
    Me reste un soucis avec l'annulation.

    Quand j'annule , ça annule bien mais j'ai une exception en arrivant sur la première ligne du RunWorkerCompleted.

    Voici les 3 fonctions du backgroundworker avec la ligne incriminée marquée en commentaire. Je ne comprends pas où est le problème dans le cas d'une annulation.

    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
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
           private void backgroundWorkerOrdre_DoWork(object sender, DoWorkEventArgs e)
            {
                ClasseBGparam args = (ClasseBGparam)e.Argument;
                Boolean PasFini = true;
     
                while (!backgroundWorkerOrdre.CancellationPending && PasFini ==true)
               {
                    ftStatus = args.MyFTDI.Read(InBuffer, (uint)args.NboctetArecevoir, ref ftRead); // ligne longue (de 2 à 15s suivant les cas)
                    PasFini = false;
                }
                e.Result = args;
     
                if (backgroundWorkerOrdre.CancellationPending)   e.Cancel = true;            
            }
     
            /**********/
            private void backgroundWorkerOrdre_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                ClasseBGparam args = (ClasseBGparam)e.Result; // Exception ici si annulation
     
                if (e.Error != null) {
                    MessageBox.Show("Erreur : " + e.Error.Message);
                }
                else if (e.Cancelled) {
                    MessageBox.Show("Tâche d'arrière plan annulée.");
                }
                else
                {
     
                    switch (InBuffer[0])
                    {
                        case ACK: statusStrip1.BackColor = System.Drawing.Color.White; toolStripStatusLabel1.Text = args.Titre + " : " + args.MessageReussite; break;
                        case NAK: statusStrip1.BackColor = System.Drawing.Color.Red; toolStripStatusLabel1.Text = args.Titre + " : " + args.MessageEchec; break;
                        case INCONNU: statusStrip1.BackColor = System.Drawing.Color.Red; toolStripStatusLabel1.Text = "La carte n'a pas reconnu l'ordre envoyé !!!!!!!!"; break;
                        default: statusStrip1.BackColor = System.Drawing.Color.Red; toolStripStatusLabel1.Text = "Accusé reception retourné par la carte inconnu !!"; break;
                    }
                }
     
                args.MyFTDI.Close();
            }
     
            /********/
            private void btAnnuler_Click(object sender, EventArgs e)
            {
                this.backgroundWorkerOrdre.CancelAsync();   
                this.btAnnuler.Visible = false;             
            }
    Après il me restera juste à gérer un timeout. J'ai prévu d'activer l'annulation sur le tick d'un timer et de positionner en même temps une variable qui permettra de faire la différence entre une annulation manuelle et ce timeout

    Merci
    Il y a 10 sortes de personnes dans le monde : ceux qui comprennent le binaire et les autres

  9. #9
    Membre chevronné Avatar de petitours
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Février 2003
    Messages
    1 935
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 935
    Points : 2 013
    Points
    2 013
    Par défaut
    je cherche pour mon exception et je ne trouve pas...

    Mais en fait je ne comprends pas comment mon code peut marcher !!

    j'ai mis une boucle
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     while (!backgroundWorkerOrdre.CancellationPending
    pour intercepter l'annulation, OK

    sauf que la tache longue qui est dedans ne boucle pas elle
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ftStatus = args.MyFTDI.Read(InBuffer, (uint)args.NboctetArecevoir, ref ftRead);
    cette ligne attend que des caractères arrivent, on est sensé rester dessus tout le temps d'attente.

    Donc j'ai deux soucis
    1) je ne comprends pas pourquoi l'annulation arrive à stopper mon DoWork
    2) Pourquoi ai-je une exception dans la fonction de sortie quand je sors sur annulation ?

    Merci pour votre aide, je commence à avoir mal aux cheveux sur ce backgroubdworker
    Il y a 10 sortes de personnes dans le monde : ceux qui comprennent le binaire et les autres

  10. #10
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    (lu en diagonale)

    le backgroundworker démarre un nouveau thread, ce qui équivant à un 2ème ligne de pas à pas simultanément à la première, et indépendante

    si on a
    i1;
    démarrage bgw;
    i2;

    i2 est exécuté pendant le bgw, ca peut être un peu avant car démarrer un thread peut prendre un peu moins d'une milliseconde, mais si on prend la suite des instructions les 2 codes sont bien exécutés en même temps



    après on n'utilise pas une classe qu'on ne connait pas directement dans son code, on l'apprend ou on la teste

    sur msdn il est dit que si on fait e.cancel = true la lecture de e.result (dans le completed) lève une exception
    http://msdn.microsoft.com/fr-fr/libr...vs.100%29.aspx

    et sinon avec le test préalable pour comprendre (ou pour vérifier si ca vient de la spécificité de notre code) ca donne :

    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
    /// class Form1
    public New() /// là je pense que le traducteur c# vb.net s'est gourré, il s'agit du constructeur (nom de la classe en c# il me semble)
    {
        InitializeComponent();
     
        System.ComponentModel.BackgroundWorker b = new System.ComponentModel.BackgroundWorker();
        b.DoWork += dowork;
        b.RunWorkerCompleted += fin;
        b.RunWorkerAsync();
    }
     
     
    private void dowork(object sender, System.ComponentModel.DoWorkEventArgs e)
    {
        System.Threading.Thread.Sleep(3000);
        e.Cancel = true;
    }
     
    private void fin(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
    {
        object r = e.Result;
        // lève une exception
    }
    là ca plante donc ca prouve que ca ne vient pas de code élaboré

    on voit au passage que la fenêtre s'affiche tout de suite, donc qu'on est sortir du constructeur, alors que le bgw est en train d'attendre 3 secondes

    je ne pense pas avoir répondu à toute tes questions car je n'ai pas tout lu, tu peux redétailler s'il reste des points que tu n'arrives pas à comprendre
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  11. #11
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Points : 2 605
    Points
    2 605
    Par défaut
    Bonjour.

    Citation Envoyé par petitours Voir le message
    je cherche pour mon exception et je ne trouve pas...
    Le try/catch est ton ami.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    try{
     
      ClasseBGparam args = (ClasseBGparam)e.Result; // Exception ici si annulation
    }
    catch(Exception ex){ MessageBox.Show(ex.Message); }
    Citation Envoyé par petitours Voir le message
    1) je ne comprends pas pourquoi l'annulation arrive à stopper mon DoWork
    Il faudrait regarder la documentation. Il est possible que le Framework kill le thread lors du cancel. Ceci expliquerait l'exception et l'annulation du DoWork.

  12. #12
    Membre chevronné Avatar de petitours
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Février 2003
    Messages
    1 935
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 935
    Points : 2 013
    Points
    2 013
    Par défaut
    Bonjour
    A force de ne trouver que des docs, des cours et des post de forum parlant de l'impossibilité d'annuler une longue ligne il a bien fallu que je remette en cause mon diagnostic :
    En fait non, ça n'arrive pas à annuler ma fonction, je me suis laissé embrouiller par tous les temps de latence de mise à jour des affichages en testant.

    Je n'ai en fait aucun moyen d'annuler la grosse ligne qui attend la réception d'un octet sur l'usb. Je ne peux qu'attendre le déclenchement du timeout qu'elle gère elle-même.

    Par ailleurs, je mets pour le moment que la tache longue dans le bgw, avec du coup obligation de passer pleins de paramètres au DoWork et à la fonction de fin. Je vais essayer de mettre plus de choses dans le DoWork de manière à limiter ces passages d'arguments.

    Merci
    Il y a 10 sortes de personnes dans le monde : ceux qui comprennent le binaire et les autres

  13. #13
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    il y a bien une méthode pour annuler une ligne longue, c'est d’interrompre le thread
    je ne suis pas sur qu'on puisse avec le backgroundworker, mais avec un system.threading.thread on peut

    lethread.abort / lethread.interrupt

    à voir si ca n'a pas d'effet de bord dans ton cas


    je ne sais pas avec quoi tu lis en usb, mais dans le framework pour les réseau et d'autres il y a des méthodes asynchrones, ce qui permet de les annuler indirectement
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  14. #14
    Membre chevronné Avatar de petitours
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Février 2003
    Messages
    1 935
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 935
    Points : 2 013
    Points
    2 013
    Par défaut
    L'utilisation des thread, les vrais, je verrai un peu plus tard, quand je serai plus à l'aise avec backgroundworker qui est si je comprends bien un composant qui prémâche et donne un cadre simple au multithreading. Parfait pour les nulls !

    Pour causer sur l'usb, j'utilise une DLL (D2XX) de chez FTDI, qui met à disposition toute une artillerie de fonctions pour gérer très simplement une com usb avec des composants de chez eux.
    Ca fonctionne extrêmement bien, mais il n'y a forcément pas autant de chose que si on travaille directement avec les couches plus basses.

    L'avantage d'un truc simple comme ça, c'est que quand on est dans une impasse, comme j'y étais là, c'est à priori que l'on ne fait pas comme il faut !

    Merci
    Il y a 10 sortes de personnes dans le monde : ceux qui comprennent le binaire et les autres

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

Discussions similaires

  1. [C#] Timer : Tache qui se repete
    Par Seth77 dans le forum Windows Forms
    Réponses: 7
    Dernier message: 18/05/2010, 21h21
  2. definition d'une tache qui s'execute toutes les secondes
    Par Mokhtar BEN MESSAOUD dans le forum Administration système
    Réponses: 3
    Dernier message: 07/08/2007, 07h19
  3. Réponses: 1
    Dernier message: 30/03/2007, 16h38
  4. barre des taches qui reste apparente
    Par arfy dans le forum Windows XP
    Réponses: 5
    Dernier message: 25/11/2005, 08h33
  5. Tâche qui ne se lance pas avec cron
    Par bugalood dans le forum Administration système
    Réponses: 3
    Dernier message: 17/10/2005, 18h13

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