none
Afficher GIF - Blocage de l'animation RRS feed

  • Question

  • Bonjour, Je fais suite à la conversation suivante :

    http://social.msdn.microsoft.com/Forums/fr-FR/vbasicfr/thread/d40cf8d0-c73a-4484-bf32-4ab6804a4a52

    Je réalise une application qui me permet de générer automatiquement des fichiers Word. Ces fichiers étant lourds, ils mettent un certain temps à s'écrire (plusieurs secondes) mais ce temps est très variable.

    fred75, que je remercie m'avait conseillé d'utiliser un gif animé que j'afficherait au lancement du chargement et que j'effacerais à la fin du chargement. Je suis donc parti sur cette solution.

    Problème, lorsque je lance mon GIF animé il s'affiche et tourne correctement. Mais dés que le fichier Word commence à se charger, le GIF animé se fige jusqu'a la fin du chargement. Enfin il s'efface comme demandé lorsque le chargement est terminé.

    Comment faire ?

    Mon code est le suivant :

     Chargement_PictureBox1.Visible = True
    
    ' la le gif fonctionne
    
    lancement du chargement du fichier Word
    
    'la le gif se fige
    
    fin du chargement du fichier
    
    Chargement_PictureBox1.Visible = False
    
    'la se gif disparait et c'est normal

    J'ai également essayé de lancer le GIF avec un sub indépendant mais le résultat est le même.

    Merci d'avance

    samedi 25 août 2012 11:06

Réponses

  • Bonjour,

    Ne pas mettre la manipulation du contrôle PictureBox dans "_charg" mais uniquement le traitement du fichier Word. Le principe est que toute modification faite sur des contrôles doit être faite par le thread ayant crée ce contrôle (ce qui provoque sinon ce message).

    Le principe serait plutôt qq chose comme :

        Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
            Button1.Enabled = False
            ProgressBar1.Style = ProgressBarStyle.Marquee
            BackgroundWorker1.RunWorkerAsync()
        End Sub
    
        Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
            Dim s As New Stopwatch
            Dim Durée As TimeSpan = TimeSpan.FromSeconds(5)
            s.Start()
            While s.Elapsed < Durée
            End While
            s.Stop()
        End Sub
    
        Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
            ProgressBar1.Style = ProgressBarStyle.Blocks
            Button1.Enabled = True
        End Sub
    Donc le contrôle est modifiée avant ou après ce travail qui est donc exécuté en arrière plan. On peut aussi mettre qq contrôles comme des cases à cocher sur le formulaire et voir que pendant ce traitement simulé, l'animation continue à tourner et les cases à cocher restent opérationnelles.


    Please always mark whatever response solved your issue so that the thread is properly marked as "Answered".

    • Marqué comme réponse Fabien69 dimanche 26 août 2012 18:36
    dimanche 26 août 2012 14:03
    Modérateur

Toutes les réponses

  • Bonjour,

    C'est simple, car votre programme n'est pas multitâches de base, il vous suffit donc d'utiliser le multithread afin d'afficher l'animation de votre image et d'en même temps pouvoir traiter votre fichier. Cela vous permet également si vous disposez de boutons sur votre application de pouvoir les utiliser pendant le traitement, car votre programme fige intégralement temporairement pendant le traitement vu qu'il ne fait qu'une chose à la fois. Je vous conseille ce lien pour en savoir plus à propos du multithread.

    En espérant vous avoir aidé.

    Cordialement

    • Modifié Pilotepro samedi 25 août 2012 12:21
    samedi 25 août 2012 12:13
  • Bonjour,

    Je pense que le plus simple pour vous est d'utiliser un BackgroundWorker, c'est un contrôle que vous trouverez dans la boite à outils rubrique composants. Il vous suffira de créer une fenêtre avec un ProgressBar en style Marquee, celle-ci va défiler en continue.


    Merci de valider par "Proposer comme réponse" si celle-ci répond a votre demande !

    samedi 25 août 2012 13:31
  • Bon, d'abord merci d'avoir pris le temps de répondre.

    Sinon, au risque de passer pour un crét...., je ne comprends pas trop comment tout cela fonctionne.

    Mon programme se compose comme celui ci :

    J'ai un formulaire nommé "main" dont le code contient mes différents sub pour la génération de mes fichiers.

    Sur ce formulaire est crée une picture box (chargement_picturebox1) avec un GIF animé dedans. (Si il est plus facile de faire une progress bar avec style marquee pourquoi pas)

    Du coup, avec ce que j'ai compris,

    1. J'ai fait glisser un background worker sur mon formulaire Main

    2. J'ai double cliqué sur le background pour gerer l'évenement DoWork

    3. J'ajoute ca :

     Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
            _charg()
        End Sub
    
    Avec le sous programme _charg suivant (_charg est dans la classe Main) :
    
      If Chargement_PictureBox1.Visible = False Then
                Chargement_PictureBox1.Visible = True
                MENU_GroupBox1.Enabled = False
                Nouveau_ouvrir_GroupBox1.Enabled = False
            Else
                Chargement_PictureBox1.Visible = False
                MENU_GroupBox1.Enabled = True
                Nouveau_ouvrir_GroupBox1.Enabled = True
            End If

    4.Ensuite dans mon sub de génération de mes fichiers Words (contenu de la classe main, je rajoute ça)

     Private Sub generation()
    
       BackgroundWorker1.RunWorkerAsync()
    
    'suite du sub
    
    End sub

    5. Je lance le programme puis la génération du fichier Word et j'obtiens le message d'erreur suivant :

    "Opération inter-threads non valide : le contrôle 'Chargement_PictureBox1' a fait l'objet d'un accès à partir d'un thread autre que celui sur lequel il a été créé."

    Du coup, je comprend pas trop vu que tout est fait à partir de la classe Main ...

    Merci de votre aide!



    • Modifié Fabien69 dimanche 26 août 2012 12:36
    dimanche 26 août 2012 12:34
  • Bonjour,

    Ne pas mettre la manipulation du contrôle PictureBox dans "_charg" mais uniquement le traitement du fichier Word. Le principe est que toute modification faite sur des contrôles doit être faite par le thread ayant crée ce contrôle (ce qui provoque sinon ce message).

    Le principe serait plutôt qq chose comme :

        Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
            Button1.Enabled = False
            ProgressBar1.Style = ProgressBarStyle.Marquee
            BackgroundWorker1.RunWorkerAsync()
        End Sub
    
        Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
            Dim s As New Stopwatch
            Dim Durée As TimeSpan = TimeSpan.FromSeconds(5)
            s.Start()
            While s.Elapsed < Durée
            End While
            s.Stop()
        End Sub
    
        Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
            ProgressBar1.Style = ProgressBarStyle.Blocks
            Button1.Enabled = True
        End Sub
    Donc le contrôle est modifiée avant ou après ce travail qui est donc exécuté en arrière plan. On peut aussi mettre qq contrôles comme des cases à cocher sur le formulaire et voir que pendant ce traitement simulé, l'animation continue à tourner et les cases à cocher restent opérationnelles.


    Please always mark whatever response solved your issue so that the thread is properly marked as "Answered".

    • Marqué comme réponse Fabien69 dimanche 26 août 2012 18:36
    dimanche 26 août 2012 14:03
    Modérateur
  • Merci de votre réponse.

    Cependant, je ne comprends pas plusieurs choses (encore...)

    1. dans _charg, il n'y a aucun traitement de fichier Word.

    2. De plus j'ai l'impression que vous voulez faire passer la génération des fichiers Word en backgroundworker. Mon application génère plusieurs Fichiers Word différents en fonction de plusieurs dizaine de variables. Ne serait-il pas plus simple de passer en backgroundWorker uniquement la process bar ou le GIF animé qui serait toujours le même peu importe le fichier Word généré?

    3. Ou est le traitement des fichiers Word dans votre exemple de code?

    4. Pouvez vous d'ailleurs commenter le contenu du sub [...] DoWork ?

    5. Je n'ai pas forcément besoin de laisser l'accès à l'utilisateur de l'application pendant la génération des fichiers Words. (c'est peut-être même plutôt l'inverse)

    Merci de votre aide


    • Modifié Fabien69 dimanche 26 août 2012 14:47
    dimanche 26 août 2012 14:46
  • 1) Oui parce que ce que vous semblez vouloir faire est de traiter la mise à jour de l'interface en arrière plan (ce qui pose problème car par principe le formulaire ne peut être mis à jour que depuis le thread qui le gère) et faire le traitement Word dans le thread principal.

    2) Je pense que cela serait plus compliqué. Généralement on laisse la mise à jour de l'interface sur le thread principal et on fait le travail en arrière plan (bien que j'ai vu des personnes faire le contraire, je pense que c'est souvent plus complexe car il faut faire attention à ne pas se mélanger les pinceaux car on finit par avoir des interfaces qui ne s'exécutent pas toutes dans le même thread en fonction du formulaire etc ce qui à terme doit être assez délicat à gérer). L'idée est que de toute façon l'utilisateur ne peut maniper que sur une UI à la fois. Une application peut par contre exécuter plusieurs travaux en arrière plan. Il semble donc plus naturel de laisser tout ce qui est interface sur le thread principal et de créer un (ou plusieurs) thread pour le travail (ou les travaux) que l'on veut lancer en arrière plan.

    3, 4) C'est représenté par le code présent dans DoWork qui pour l'instant ne fait qu'utiliser un objet permettant de mesurer un temps écoulé pour attendre 5 secondes (c'est juste pour montrer qu'une boucle peut se dérouler alors que la barre de progression continue à se mettre à jour et que l'interface reste réactive).

    5) Ici aussi, je désactive le bouton permetttant de lancer le traitement. Je pourrais par contre activer un bouton Annuler qui permettrait par exemple d'interrompre le traitement avant la fin.


    Please always mark whatever response solved your issue so that the thread is properly marked as "Answered".

    dimanche 26 août 2012 15:55
    Modérateur
  • Merci beaucoup, ça fonctionne très bien votre truc. Je l'ai adapté pour le faire avec un GIF animé et c'est nickel.

    Merci encore.

    dimanche 26 août 2012 18:36