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

VB.NET Discussion :

Thread : Operation inter-threads non valide


Sujet :

VB.NET

  1. #1
    Membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2006
    Messages
    128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Juillet 2006
    Messages : 128
    Points : 61
    Points
    61
    Par défaut Thread : Operation inter-threads non valide
    Après avoir buté sur les évenements , je pensais que ce serait simple et que j'aurais juste à mettre mon sub en thread, mais non...

    dans button1_click, j'ai remplacer mon appel direct "RempliListView(mesSources)" par :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Dim th As New Threading.Thread(AddressOf RempliListView)
    th.Start(mesSources)
    mais j'obtiens :

    Une exception non gérée du type 'System.InvalidOperationException' s'est produite dans System.Windows.Forms.dll

    Informations supplémentaires : 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éé.

    Pourtant mon appel au thread est bien fait dans la classe du formulaire...

  2. #2
    Expert éminent Avatar de Graffito
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    5 993
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 993
    Points : 7 903
    Points
    7 903
    Par défaut
    Un Thread différent du thread principal de l'application ne peut pas modifier des Controls présents dans les Form.

    Par exemple, je ne vois aucune solution pour avoir une visualisation d'avancement de 1 à n d'un process qui va initialiser les controls de n forms.

  3. #3
    Membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2006
    Messages
    128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Juillet 2006
    Messages : 128
    Points : 61
    Points
    61
    Par défaut
    Citation Envoyé par Graffito Voir le message
    Un Thread différent du thread principal de l'application ne peut pas modifier des Controls présents dans les Form.

    Par exemple, je ne vois aucune solution pour avoir une visualisation d'avancement de 1 à n d'un process qui va initialiser les controls de n forms.
    >qui va initialiser les controls de n forms
    non ça n'initialise pas, ça doit mettre à jour "l'état".

    Un peu comme un gestionnaire de téléchargement ou autre...

    qui met à jour chaque "ligne" avec sa vitesse de téléchargement par exemple.

  4. #4
    Membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2006
    Messages
    128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Juillet 2006
    Messages : 128
    Points : 61
    Points
    61
    Par défaut
    Citation Envoyé par Graffito Voir le message
    Un Thread différent du thread principal de l'application ne peut pas modifier des Controls présents dans les Form.

    Par exemple, je ne vois aucune solution pour avoir une visualisation d'avancement de 1 à n d'un process qui va initialiser les controls de n forms.
    autant pour moi, j'ai appelé l'initialisation de mon listview...

    du coup j'ai modifié, mais mon problème est déporté ailleurs (dans le retour d'événement "S2")

    correction dans Button1_Click :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
     RempliListView(mesSources)
     
            Dim th As New Threading.Thread(AddressOf MajLesSources)
            th.Start()
    ...etc...
     
     
    Private Sub MajLesSources()
            mesSources.majSource()
        End Sub
    S2 qui est à l'écoute, me m'indique du coup que la modification sur le listview et faite par autre chose que le form :

    Une exception non gérée du type 'System.InvalidOperationException' s'est produite dans System.Windows.Forms.dll

    Informations supplémentaires : 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éé.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Private Sub S2(ByVal sender As Object, ByVal e As MajSourceEventArgs)
            Dim lasource As Source = sender
            ListView1.Items(lasource.Nom).SubItems(1).Text = lasource.Champ2
            ' MessageBox.Show(Me, "Detection Maj source", "Maj Source")
        End Sub

  5. #5
    Membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2006
    Messages
    128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Juillet 2006
    Messages : 128
    Points : 61
    Points
    61
    Par défaut
    Bonjour,

    Je viens de passer une partie de la nuit et de trouver quelque chose qui fonctionne ! enfin presque...

    Pour ce faire j'ai limiter mon exemple, mais je me retrouve avec quelque chose d'étrange :
    - 2 Threads, l'un avec une pause de 2000ms et l'autre de 500ms, je devrais donc avoir dans mon affichage l'un qui s'affiche plus vite que l'autre, ce qui n'est pas le cas
    - le freeze du formulaire, quand j'ai lancé le traitement, je ne peux pas bouger, bref rien faire sur le formulaire tant que les 2 threads n'ont pas finis.

    Voici le code (beaucoup pour pas grand chose au final), le formulaire contien 1 Richtextbox et un bouton

    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
     Public Structure ParamTh
            Dim texte As String
            Dim pause As Integer
        End Structure
     
    Private Delegate Sub UIDelegate(ByVal val As Integer, ByVal texte As String)
     
      Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
     
            Dim thread = New System.Threading.Thread(AddressOf del)
            'thread.IsBackground = True
            Dim thread2 = New System.Threading.Thread(AddressOf del)
            'thread2.IsBackground = True
            Dim th1 As ParamTh
            th1.texte = "Thread1"
            th1.pause = 2000
            thread.Start(th1)
     
            Dim th2 As ParamTh
            th2.texte = "Thread2"
            th2.pause = 500
            thread2.Start(th2)
     
        End Sub
     
        Private Sub AddTextToUI(i As Integer, texte As String)
            RichTextBox1.AppendText(texte & Environment.NewLine)
            Thread.Sleep(i)
            RichTextBox1.Update()
        End Sub
     
        Private Sub del(ByVal param As ParamTh)
            For i As Integer = 0 To 10
                Me.Invoke(New UIDelegate(AddressOf AddTextToUI), param.pause, param.texte)
            Next
        End Sub
    Merci d'avance pour vos lumières !

  6. #6
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 177
    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 177
    Points : 25 125
    Points
    25 125
    Par défaut
    non me.invoke fait que ce qui suit est appelé sur le thread principal (c'est comme si ca changeait de thread)
    donc c'est ton thread principal qui fait le .sleep
    si tu veux 2 délais différents, c'est au thread de faire le .sleep (de plus un sleep sur le thread principal freeze l'interface)
    et je ne vois pas ce que ta boucle for fait ici

    un thread ne peut faire qu'une chose à la fois, vu que tu as 2 threads qui essaye de repasser sur le thread principal, c'est chacun leur tour

  7. #7
    Membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2006
    Messages
    128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Juillet 2006
    Messages : 128
    Points : 61
    Points
    61
    Par défaut
    Citation Envoyé par Pol63 Voir le message
    non me.invoke fait que ce qui suit est appelé sur le thread principal (c'est comme si ca changeait de thread)
    donc c'est ton thread principal qui fait le .sleep
    si tu veux 2 délais différents, c'est au thread de faire le .sleep (de plus un sleep sur le thread principal freeze l'interface)
    et je ne vois pas ce que ta boucle for fait ici

    un thread ne peut faire qu'une chose à la fois, vu que tu as 2 threads qui essaye de repasser sur le thread principal, c'est chacun leur tour
    >c'est ton thread principal qui fait le .sleep
    Ok, j'ai mis ceci pour "ralrentir" et simulé un long traitement, je ne vois pas comment dire au thread "en cours" de faire une pause alors, si ce n'est les déclarer en "global"

    >je ne vois pas ce que ta boucle for fait ici
    La boucle est là pour simulé plusieurs appels (comme pour mon projet "principal", l'extraction des informations des fichiers un à un mais à distribué à différent thread du coup...), mais en effet, je devrais peut-être tenter de faire une sorte de "tache" à traiter par des threads.

    Donc un tableau de x threads, sans que les thread ne prenne la même tâche à traiter.

  8. #8
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 177
    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 177
    Points : 25 125
    Points
    25 125
    Par défaut
    quand on a du chargement à faire
    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
     
    private _donnees as quelque chose '(collection ou autre) 
     
    sub demarrerchargement
      dim th as new thread(adressof chargement)
      th.start
    end sub
     
    sub chargement
      ' traitement qui remplit _donnees
      me.invoke(new action(adressof finchargement))
    end sub
     
    sub finchargement
       'remplissage des controles à partir de _donnees
    end sub

  9. #9
    Membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2006
    Messages
    128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Juillet 2006
    Messages : 128
    Points : 61
    Points
    61
    Par défaut
    Citation Envoyé par Pol63 Voir le message
    quand on a du chargement à faire
    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
     
    private _donnees as quelque chose '(collection ou autre) 
     
    sub demarrerchargement
      dim th as new thread(adressof chargement)
      th.start
    end sub
     
    sub chargement
      ' traitement qui remplit _donnees
      me.invoke(new action(adressof finchargement))
    end sub
     
    sub finchargement
       'remplissage des controles à partir de _donnees
    end sub

    Donc si je comprends bien.
    Je vais démarrer à l'envers :

    sub finchargement : mise à jour de mes données dans mon listview (Sub appelé par la remonté d'événement) (code dans mon formulaire)

    sub chargement : Récupération des informations dans mes fichiers (la phase qui est normalement lente) et raiseEvent lorsque les données sont récupérées (code dans ma classe ? dans ce cas je peux pas faire le "me.invoke")

    sub demarrerchargement : Appel à la partie chargé de faire l'extraction des informations (code dans mon formulaire)

    private _donnees : ma collection (Dictionary(Of String, Object)) (qui est présent dans ma classe)

  10. #10
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 177
    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 177
    Points : 25 125
    Points
    25 125
    Par défaut
    si ton code de chargement des données est sur une autre classe que le form :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    sub demarrerchargement
      dim th as new thread(adressof instanceclasse.chargement)
      th.start
    end sub
     
     
    sub finchargement handles instanceclasse.fini
       if me.invokerequired then ' invokerequired vaut true si le thread exécutant le code est différent du thread ayant créé le controle
         me.invoke(finchargement) '  on demande à revenir sur le thread principal, ca re rentre ici même mais invokerequired vaudra false
         exit sub
       end if
       'remplissage des controles
    end sub
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    sub chargement ' sur autre classe
      ' traitement qui remplit les données
      raiseevent fini
    end sub

    en fait ce n'est pas le moyen le plus propre, mais les autres moyens sont plus compliqués et nécessite un peu plus de code
    il y a aussi des moyens moins propre pour que l'event soit relayé sur le thread principal directement


    (...)

    en fait il y a aussi le backgroundworker, qui reste plus propre et dont les events sont relayés sur le thread appelant (donc principal dans notre cas)
    c'est une classe encapsulant le démarrage d'un thread, une possibilité d'annuler (à coder soi même mais c'est prévu pour), un event de progression (à gérer soit même aussi) et un event de fin

  11. #11
    Membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2006
    Messages
    128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Juillet 2006
    Messages : 128
    Points : 61
    Points
    61
    Par défaut
    J'ai essayé de refaire un projet "propre" (GestionVideo ci joint), mais sans succès. En effet je travaillais depuis un projet créé et fourni par MediaInfo (MediaInfo_DLL_0.7.70_Windows_x64_WithoutInstaller).
    Dès que je ne par pas de leur projet je ne peux pas faire le new de MediaInfoDLL.vb (Handle = MediaInfo_New()) j'obtiens Tentative de chargement d’un programme de format incorrect. (Exception de HRESULT : 0x8007000B) dans mon projet "GestionVideo" mais pas dans le leur d'origine sans savoir pourquoi, je n'ai pas vu de différence. C'est pourquoi j'avais commencé à travaillé sur leur projet.

    J'ai donc joint ici les 2 projets.

    Pour info la structure pour la récupération des fichier doit être :
    Mon Fim\Mon Film CD1.avi
    Mon Fim\Mon Film CD2.avi
    Mes Vacances\Mes Vacances.mkv

    Bon je vais me reprendre un café, je dois approché la trentaine depuis hier soir...

    Nota: je viens de trouver à l'instant pourquoi le projet ne marché pas ailleurs (dans la gestion du projet / Compiler / Préférer 32 bits est coché par défaut, la DLL étant à l'origine 64 Bits...
    Le café çà aide
    Fichiers attachés Fichiers attachés

  12. #12
    Membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2006
    Messages
    128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Juillet 2006
    Messages : 128
    Points : 61
    Points
    61
    Par défaut
    Ca y est presque, mon "finchargement" est :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
      Private Sub MajLVExtraction(ByVal sender As Object, ByVal e As ExtractionGeneraleTermineEventArgs)
            Dim source As Video = sender
    
            If Me.InvokeRequired Then
                Me.Invoke(MajLVExtraction, sender)
            End If
    
            ListView1.Items(source.FullPath).SubItems(ListView1.Columns.IndexOfKey("durée")).Text = source.GeneralInfos("Duration/String3")
            ListView1.Items(source.FullPath).SubItems(ListView1.Columns.IndexOfKey("FileSize")).Text = source.GeneralInfos("FileSize")
            ListView1.Items(source.FullPath).SubItems(ListView1.Columns.IndexOfKey("GetInfos")).Text = "Ok"
            ListView1.Update()
        End Sub
    du coup mon invoke doit passer des paramètres...

  13. #13
    Inactif  

    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2012
    Messages
    4 903
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2012
    Messages : 4 903
    Points : 10 166
    Points
    10 166
    Billets dans le blog
    36
    Par défaut
    Bonjour,

    Ayant cliqué un peu par hasard sur la question et ensuite ayant vu "mediainfo", je me permets de mentionner qu'il existe un "wrapper" .net pour mediainfo:

    C'est MediaInfonet chez SourceForge



    Le blog de l'auteur (Tony George) avec quelques exemples


    Quelques expériences personnelles avec le composant.

    N.B. Je ne garantis pas que c'est une œuvre géniale, mais bon. C'était avant les exemples en VB sur le site de l'auteur et en regardant les variables et les objets sans les fenêtres de débogage et dans l'Explorateur d'objets.

  14. #14
    Membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2006
    Messages
    128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Juillet 2006
    Messages : 128
    Points : 61
    Points
    61
    Par défaut
    Citation Envoyé par clementmarcotte Voir le message
    Bonjour,

    Ayant cliqué un peu par hasard sur la question et ensuite ayant vu "mediainfo", je me permets de mentionner qu'il existe un "wrapper" .net pour mediainfo:

    C'est MediaInfonet chez SourceForge



    Le blog de l'auteur (Tony George) avec quelques exemples


    Quelques expériences personnelles avec le composant.

    N.B. Je ne garantis pas que c'est une œuvre géniale, mais bon. C'était avant les exemples en VB sur le site de l'auteur et en regardant les variables et les objets sans les fenêtres de débogage et dans l'Explorateur d'objets.
    Justement, je suis parti de la version c# pour la convertir en Vb.Net à l'aide d'un site de conversion, j'ai testé le wrapper dont tu parles (plus vielle) et je préfére celle que j'ai faite. Et par hasard dans un autre répertoire, j'ai vu la version Vb.net fournie dans un autre répertoire qui au finale est quasi la même que celle que j'ai faite.

    Sinon j'ai abandonné mon problème mon invoke pour la journée, j'en pouvais plus.

Discussions similaires

  1. Réponses: 7
    Dernier message: 09/05/2014, 19h14
  2. Operation inter thread
    Par anatw73 dans le forum VB.NET
    Réponses: 2
    Dernier message: 03/02/2011, 02h33
  3. Accès inter-threads non valide et BitmapImage
    Par Louis745 dans le forum Silverlight
    Réponses: 6
    Dernier message: 31/10/2010, 16h16
  4. Opération inter-threads non valide
    Par nakk01 dans le forum Windows Forms
    Réponses: 5
    Dernier message: 26/05/2009, 01h43
  5. Erreur : Opération inter-threads non valide
    Par cadeau dans le forum C++/CLI
    Réponses: 1
    Dernier message: 12/12/2006, 09h07

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