Probléme avec inter-threads avec listview1

miska59 Messages postés 6 Date d'inscription dimanche 12 mars 2017 Statut Membre Dernière intervention 8 janvier 2022 - 7 avril 2017 à 08:07
Whismeril Messages postés 19020 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 15 avril 2024 - 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

3 réponses

Whismeril Messages postés 19020 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 15 avril 2024 656
7 avril 2017 à 12:18
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.
0
vb95 Messages postés 3472 Date d'inscription samedi 11 janvier 2014 Statut Contributeur Dernière intervention 13 avril 2024 169
Modifié le 7 avril 2017 à 12:36
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. 
0
Whismeril Messages postés 19020 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 15 avril 2024 656
8 avril 2017 à 00:03
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



0
Rejoignez-nous