Probléme avec inter-threads avec listview1

miska59 3 Messages postés dimanche 12 mars 2017Date d'inscription 24 avril 2017 Dernière intervention - 7 avril 2017 à 08:07 - Dernière réponse : Whismeril 10576 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 16 décembre 2017 Dernière intervention
- 8 avril 2017 à 00:03
Bonjour,
j'ai une message erreur avec threads dans listview1 :
Opération inter-threads non valide : le contrôle 'ListView1' a fait l'objet d'un accès à partir d'un thread autre que celui sur lequel il a été créé.

Voici le code :
Dim i As Integer = 0
Do While (i <= (Convert.ToInt32(Me.TextBox1.Text) - 1))
Dim parameter As Integer = i
Me.startThreads(i) = New Thread(New ParameterizedThreadStart(AddressOf Me.checkProxys))
Me.startThreads(i).Start(parameter)
i += 1
Loop

Private Sub checkProxys()
Do While Running
For i As Integer = 0 To ListView1.Items.Count - 1
Dim lv As ListViewItem = ListView1.Items(i) <= message erreur
Dim ip As String = lv.Text
Dim port As String = lv.SubItems(1).Text
Dim proxy As String = ip + ":" + port
Try
Dim request As System.Net.HttpWebRequest = System.Net.HttpWebRequest.Create("http://www.google.fr")
request.Proxy = New WebProxy(proxy)
request.Timeout = NumericUpDown2.Value * 1000
Dim response As System.Net.HttpWebResponse = request.GetResponse()
If response.StatusCode = HttpStatusCode.OK Then
lv.SubItems.Add("OK")
lv.SubItems(0).ForeColor = Color.DarkGreen
Else
lv.SubItems.Add("Failed")
lv.SubItems(0).ForeColor = Color.Red
End If
Catch
lv.SubItems.Add("Failed")
lv.SubItems(0).ForeColor = Color.Red
End Try
Next
Loop
Me.startThreads(1).Abort()
End Sub


Pouvez-vous me dire comment corriger avec listview1 pour éviter ce message erreur?
Merci de votre réponse
Afficher la suite 

3 réponses

Répondre au sujet
Whismeril 10576 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 16 décembre 2017 Dernière intervention - 7 avril 2017 à 12:18
0
Utile
Bonjour

L'accès aux contrôles n'est autorisé que depuis le thread du Form.
Depuis un autre thread (sauf éventuellement les backgroundworker qui ont un mécanisme propres) il faut utiliser un dispatcher. Cet objet permet d'appeler une méthode d'un thread depuis un autre et de transmettre des paramètres. C'est cette méthode qui agira sur la listeview.

Je ne peux pas de donner d'exemple maintenant, mais ça se trouve sur le Net.
Commenter la réponse de Whismeril
vb95 1388 Messages postés samedi 11 janvier 2014Date d'inscriptionContributeurStatut 15 décembre 2017 Dernière intervention - Modifié par vb95 le 7/04/2017 à 12:36
0
Utile
Bonjour
La listview appartient au thread principal ( celui de la Form où elle a été créée) .
Les objets de l'interface (du thread principal) ne sont pas accessibles dans le thread d'arrière plan et ta listview en fait partie .
Seules les variables sont accessibles entre les 2 threads
La solution est de faire un tableau dans la Form principale qui sera organisé ainsi :
- une variable String pour le contenu de la ligne de la listview
- une variable de type Color pour la couleur de la ligne

dans le thread ChekProxy ( celui d'arrière-plan) tu utilises ce tableau sans accéder à la listview du thread principal ni aucun autre contrôle d'ailleurs .
Au retour dans le thread principal tu remplis ta listview avec le tableau
La solution de Whismeril ( que je salue au passage) est plus difficile à mettre en œuvre mais fonctionne aussi sans souci : le dispatcher gère les "accès" inter-threads entre le thread d'arrière-plan et le thread principal .

Quand aux BackGroundWorker uniquement une ProgressBar est "accessible" depuis l'arrière plan pour montrer la progression du thread en arrière plan

Pour plus de précision voir http://plasserre.developpez.com/cours/vb-net/?page=windows-forms5#LX-R

La théorie, c'est quand on sait tout et que rien ne fonctionne. La pratique, c'est quand tout fonctionne et que personne ne sait pourquoi. 
Commenter la réponse de vb95
Whismeril 10576 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 16 décembre 2017 Dernière intervention - 8 avril 2017 à 00:03
0
Utile
Bonsoir

Exemple 1, opération interthread simple
tu copies ce code dans le thread dans ta formulaire
    Dim disp As Dispatcher = Dispatcher.CurrentDispatcher 'initialise le dispatcher


Tu enlèves la ligne qui bugues.
Et à chaque ligne ou tu ajoutes un subitem, tu remplaces par
disp.BeginInvoke(New Action(Sub() ListView1.Items(i).SubItems.Add("Saisir le texte ici")))'le dispatcher écrit directement dans la ListView


Exemple 2
tu copies ce code dans le thread dans ta formulaire
    Dim disp As Dispatcher = Dispatcher.CurrentDispatcher

    Sub AjouteListeView(Index As Integer, Texte As String)'une méthode gère l'ajout du subitem et la couleur
        ListView1.Items(Index).SubItems.Add(Texte)

        Select Case Texte
            Case "OK"
                ListView1.Items(Index).SubItems(0).ForeColor = Color.DarkGreen

                'etc
        End Select
    End Sub


    Private Delegate Sub TwoArgsDelegate(Index As Integer, Texte As String)


Tu enlèves la ligne qui bugues.
Et à chaque ligne ou tu ajoutes un subitem, tu remplaces par
disp.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, New TwoArgsDelegate(AddressOf AjouteListeView), i, "Saisir le texte ici")'le dispatcher appelle la méthode



Commenter la réponse de Whismeril

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.