none
Placer un code dans un BackGroundWorker RRS feed

  • Question

  • Bonjour,

    Je voudrais mettre ce code ci-dessous dans un backgroundworker sens qu'il y est ce message d'erreur :

    - Cross-thread operation not valid: Control 'ListView' accessed from a thread other than the thread it was created on.

    Voici le code que je voudrais mettre dans un BackGroundWorker :

    Dim obj As New cls_film_search

    Dim Mov As cls_movie_tags

    Me.Listview1.Items.Clear()

    For Each mov In cls_film_search.get_propositions(Me.Textbox1.Text)

    Dim elt As New ListViewItem

    elt.Text = mov.title

    elt.Tag = mov

    ListView1.Items.Add(elt)

    Next

    End Sub

    - Ce bout de code (incomplet) permet de faire une recherche dans une page html....

    Merci d'avance pour votre aide.

    jeudi 25 janvier 2007 19:11

Réponses

  • Lors de l'appel : bgw.RunWorkerAsync(Me.Textbox1.Text)

    Dans le DoWork tu récupère le texte qui est en argument :

    bgw_DoWork(object sender, DoWorkEventArgs e)

    Dim obj As New cls_film_search

    Dim Mov As cls_movie_tags

    Dim MonTexte As String

    MonTexte = e.Argument.ToString()

    For Each mov In cls_film_search.get_propositions(MonTexte )

    Dim elt As New ListViewItem

    elt.Text = mov.title

    elt.Tag = mov

    ((BackgroundWorker)sender).ReportProgress(0, elt) '<- Envoie l'information au ProgressChanged

    Next

    end sub

     

    Et tu récupère l'infos dans le ProgressChanged :

    bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)

    (ListViewItem)e.UserState

    Voilà en gros à quoi cela ressemble. Désolé pour la syntaxe, moi je code en C#... Mais en gros c'est comme cela que cela se fait. Dans le doWork je fais tout le traitement qui consomme du temps, sans jamais appelé des objets de mon interface (Qui ont été créé dans un autre thread) et j'utilise la méthode ProgressChanged (Qui est dans le même thread que l'interface) pour mettre à jour mon interface.

    jeudi 25 janvier 2007 22:06
    Modérateur

Toutes les réponses

  • Tu ne peux pas accèder aux contrôles d'une interface dans le DoWork d'un background Worker. Tu dois utiliser les méthodes ProgressChanged( avec l'appel de ReportProgress dans le DoWork backgroundworker) et RunWorkerCompleted.

    Tu peux passez des arguments à ces 2 méthodes. Mais attention, mettre à jour aussi souvent l'interface va quand même faire geler ton application, donc pas intéressant d'utiliser le backgroundworker.

    Tu peux allez voir http://msdn2.microsoft.com/fr-fr/library/system.componentmodel.backgroundworker_members(VS.80).aspx et http://msdn2.microsoft.com/fr-fr/library/system.componentmodel.backgroundworker(VS.80).aspx

    jeudi 25 janvier 2007 20:02
    Modérateur
  • Merci pour ta reponse ;)

    Es-ce que tu aurrais une autre solution que le BackGroundWorker ?

     

    Merci.

    jeudi 25 janvier 2007 20:10
  • Pourquoi désirais tu un BackgroundWorker (BGW) au départ, es-ce que la tâche que tu lance est longue, car tu peux utiliser le BGW. Tu passe ton texte que tu as dans ton textbox a ton BGW, et tu fais un reportProgress(0,elt).

    puis dans le ProgressChanged, tu prend l'argument et tu l'ajoute a ton listView et cela devrait fonctionner. La fonction ProgressChanged est dans le même thread que l'interface, donc tu peux utiliser ton listview.

    jeudi 25 janvier 2007 21:13
    Modérateur
  • Oui la tâche est plus ou moin longue selon la recherche effectuer...

    Je n'est pas tres bien compris comment je passe le texte de la TextBox au BGW. Es-ce que tu pourrais me donner un exemple ?

    Merci :)

    jeudi 25 janvier 2007 21:29
  • Lors de l'appel : bgw.RunWorkerAsync(Me.Textbox1.Text)

    Dans le DoWork tu récupère le texte qui est en argument :

    bgw_DoWork(object sender, DoWorkEventArgs e)

    Dim obj As New cls_film_search

    Dim Mov As cls_movie_tags

    Dim MonTexte As String

    MonTexte = e.Argument.ToString()

    For Each mov In cls_film_search.get_propositions(MonTexte )

    Dim elt As New ListViewItem

    elt.Text = mov.title

    elt.Tag = mov

    ((BackgroundWorker)sender).ReportProgress(0, elt) '<- Envoie l'information au ProgressChanged

    Next

    end sub

     

    Et tu récupère l'infos dans le ProgressChanged :

    bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)

    (ListViewItem)e.UserState

    Voilà en gros à quoi cela ressemble. Désolé pour la syntaxe, moi je code en C#... Mais en gros c'est comme cela que cela se fait. Dans le doWork je fais tout le traitement qui consomme du temps, sans jamais appelé des objets de mon interface (Qui ont été créé dans un autre thread) et j'utilise la méthode ProgressChanged (Qui est dans le même thread que l'interface) pour mettre à jour mon interface.

    jeudi 25 janvier 2007 22:06
    Modérateur
  • Merci encore une fois pour ta réponse ;)

    J'ai crée le code comme tu la expliqué mais j'ai ce message d'erreur lors de l'éxécution du programme :

    This BackgroundWorker states that it doesn't report progress. Modify WorkerReportsProgress to state that it does report progress.

     D'aprés ce que j'ai compris au message je dois modifier sa :

    Me.BackgroundWorker1.RaportProgress(0, elt) ?

    vendredi 26 janvier 2007 18:21
  • Non, en fait tu dois dire au BGW que permet de rapporter la progression (Cela devrait selon moi être a vrai tout le temps, mais par défaut, il ne supporte ni le rapport de progression ni l'annulation).

    Soit que tu vas dans le designer et tu mets la propriété du BGW WorkerReportsProgress = True ou par le code :

    Me.BackgroundWorker1.WorkerReportsProgress = true

    J'oublie toujours ce petit détail, ne pense pas que je voulais te cacher quelque chose :)

    vendredi 26 janvier 2007 19:28
    Modérateur
  • Merci beaucoup pour ton aide !!! Sa ma beaucoup aider ! Sa fonctionne a merveille :D

    Si tu as Live Messenger voici mon adresse : blaster681@hotmail.com je serais ravis de t'envoyer le résultat ;)

    Merci beaucoup a toi ;)

    vendredi 26 janvier 2007 19:53