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

C# Discussion :

Operation inter-thread multiples ToolStripMenuItem


Sujet :

C#

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Etudiant
    Inscrit en
    Avril 2014
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Etudiant

    Informations forums :
    Inscription : Avril 2014
    Messages : 12
    Points : 6
    Points
    6
    Par défaut Operation inter-thread multiples ToolStripMenuItem
    Bonjour,

    Je suis actuellement entrain de créer un explorateur de fichier distants via le protocole TCP, chaque client est affiché dans une ListView et lorsque qu'on double clic dessus l'un, la fenêtre de l'explorateur associée au client s'affiche.

    J'ai donc un objet Dictionnary<ListViewItem, Client> clients, où Client contient le socket et la fenêtre associée au client.
    De ce fait lorsque l'on double-clic dessus un Lvi, je fais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    clients[le lvi sélectionné].FileExplorer.ShowDialog();
    Jusque là tout va bien, dans la liste des fichiers j'ai un menu contextuel qui contient des ToolStripMenuItem s'affichant sans problèmes. Cependant j'ai ajouté d'autres TSMI a ceux présents, de façon 'imbriqué', voici un schéma :
    - Supprimer
    - Renommer
    - Créer
    -- Un dossier
    -- Un fichier
    - Dossiers spéciaux
    -- Documents
    -- Images
    -- AppData
    --- Roaming
    --- Local
    --- LocalLow
    - Blabla
    - Blabla

    Je peux parfaitement afficher Créer > Un dossier ou Un fichier, en revanche des que je passe ma souris sur Dossier spéciaux, qui contient un 'enfant' supplémentaire de TSMI, une exception de type InvalidOperationException est levée me signalant qu'il y a eu une opération inter-thread.
    Et le débogueur indique l'erreur a la ligne ou je fais apparaitre la fenêtre (Avec ShowDialog()).

    Du coup je me pose plusieurs questions ... Comment cela se fait-il que dans le cas de Créer Un dossier ou Un fichier, il n'y a pas d'exception, et dans le cas où il y a des sous-TSMI supplémentaires il y a l'exception ?
    J'ai vérifié et aucun thread ne fait un accès a une partie d'un contrôle a ce moment là, quand a la stack trace, que j'interprète peut être mal, il y a rapport avec une certaine méthode ShowDropDown qui viendrai je suppose du controle qui ne s'affiche pas car l'exception est levée a ce moment-là.

    Je sais que cela parait peut être flou, bien que cela soit un pavé, mais je voulais être le plus clair possible ! Merci par avance.

    Edit : voici le message de l'exception : Informations supplémentaires : Opération inter-threads non valide : le contrôle '' a fait l'objet d'un accès à partir d'un thread autre que celui sur lequel il a été créé.
    (Pas de nom du contrôle, est-ce normal ?)

    Et la stacktrace :
    à System.Windows.Forms.Control.get_Handle()
    à System.Windows.Forms.Control.SetBoundsCore(Int32 x, Int32 y, Int32 width, Int32 height, BoundsSpecified specified)
    à System.Windows.Forms.ToolStrip.SetBoundsCore(Int32 x, Int32 y, Int32 width, Int32 height, BoundsSpecified specified)
    à System.Windows.Forms.ToolStripDropDown.SetBoundsCore(Int32 x, Int32 y, Int32 width, Int32 height, BoundsSpecified specified)
    à System.Windows.Forms.Control.SetBounds(Int32 x, Int32 y, Int32 width, Int32 height, BoundsSpecified specified)
    à System.Windows.Forms.Control.set_Location(Point value)
    à System.Windows.Forms.ToolStripDropDown.set_Location(Point value)
    à System.Windows.Forms.ToolStripDropDownItem.ShowDropDownInternal()
    à System.Windows.Forms.ToolStripDropDownItem.ShowDropDown(Boolean mousePush)
    à System.Windows.Forms.ToolStripMenuItem.OnMenuAutoExpand()
    à System.Windows.Forms.MenuTimer.OnTick(Object sender, EventArgs e)
    à System.Windows.Forms.Timer.OnTick(EventArgs e)
    à System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m)
    à System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
    à System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
    à System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
    à System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
    à System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
    à System.Windows.Forms.Application.RunDialog(Form form)
    à System.Windows.Forms.Form.ShowDialog(IWin32Window owner)
    à System.Windows.Forms.Form.ShowDialog()
    à Kwartz.Interfacer.ShowFileManager(ListViewItem listViewItem) dans e:\Programmation\Projets\Travaux en cours\ProjectName\ProjectName\Interfacer.cs:ligne 267

  2. #2
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 485
    Points
    5 485
    Par défaut
    Bonjour.

    Les contrôles UI ne peuvent être modifiés que depuis le thread UI. Pour réaliser des modifications depuis un autre thread il te faut donc placer un callback dans la file d'attente du thread UI, qui exécutera ton callback dès que possible. Je t'invite à consulter la doc pour Control.Invoke et BeginInvoke.

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Etudiant
    Inscrit en
    Avril 2014
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Etudiant

    Informations forums :
    Inscription : Avril 2014
    Messages : 12
    Points : 6
    Points
    6
    Par défaut
    Bonjour et merci de ta réponse ! En effet j'ai déjà pas mal utilisé Control.Invoke (Avec la condition InvokeRequired) a travers mon projet afin d'effectuer des modifications UI demandées depuis un autre thread. Mais dans ce cas-là je ne comprends pas ce qui cause l'exception vu qu'aucun thread ne demande quoique ce soit ... (Je n'ai qu'un second thread en arrière plan qui s'occupe des sockets).

    Comment puis-je implémenter le call back ? J'ai déjà essayé d'appeler la fenêtre avec Invoke mais je m'heurte a une exception dont je me doutais, que cela ne peut être effectué tant que le handle de la form n'a pas été crée.

  4. #4
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 485
    Points
    5 485
    Par défaut
    Au temps pour moi. Aurais-tu par hasard créé la fenêtre ou ses menus sur un autre thread que celui où elle est rendue visible ?
    Sinon, pourrais-tu me montrer le code utilisé pour créer les menus ?

  5. #5
    Futur Membre du Club
    Homme Profil pro
    Etudiant
    Inscrit en
    Avril 2014
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Etudiant

    Informations forums :
    Inscription : Avril 2014
    Messages : 12
    Points : 6
    Points
    6
    Par défaut
    Non tout est géré dans le même thread concernant l'affichage ... C'est ça que j'ai du mal à comprendre ...
    J'ai fait un petit gif en 'action' pour résumer la situation :
    http://image.noelshack.com/fichiers/...-exception.gif

    Et de plus ça le fait aussi avec une autre fenêtre que je fais apparaître par la même manière, à savoir :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    clients[le lvi sélectionné].AutreFenetre.ShowDialog();
    Dès qu'un menu contextuel possède 2 'étages' de ToolStripMenuItem, l'exception se génère lorsque je veux afficher les étages.

    Du coup je me demande si cela viendrai pas de ma méthode pour associer une fenêtre à un client, les données Data de l'exception me renvoit ceci ... :
    {System.Collections.ListDictionaryInternal}

  6. #6
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 485
    Points
    5 485
    Par défaut
    Dans ton autre fenêtre, le menu est-il identique ? Parce que je suis surpris que le menu lui-même pose ce genre de problème. Effectivement j'aurais plutôt regardé du côté du databinding ou du code de création (à mon avis le menu n'existe pas encore au moment où le dropdown est requis).

    Cela dit ListDictionaryInternal est un type souvent rencontré pour l'exception Data, ça ne veut rien dire en soi, ce n'est qu'un conteneur utilisé pour y placer les données éventuellement intéressantes pour toi. De même que l'absence de nom pour le contrôle n'est pas significatif.

  7. #7
    Futur Membre du Club
    Homme Profil pro
    Etudiant
    Inscrit en
    Avril 2014
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Etudiant

    Informations forums :
    Inscription : Avril 2014
    Messages : 12
    Points : 6
    Points
    6
    Par défaut
    En effet la structure du menu est identique, voici un screen :
    http://puu.sh/8FkDa.png

    Si je passe la souris sur 33 avec le TSMI 584512 présent, exception, si je retire ce dernier, tout baigne ...

    Merci pour ces précisions concernant Data, je n'ai pas l'habitude d'analyser les exceptions de fond en comble vu qu'en général ce sont juste des petites erreurs.

  8. #8
    Futur Membre du Club
    Homme Profil pro
    Etudiant
    Inscrit en
    Avril 2014
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Gard (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Etudiant

    Informations forums :
    Inscription : Avril 2014
    Messages : 12
    Points : 6
    Points
    6
    Par défaut
    Petite erreur de ma part, la fenêtre n'est pas crée a partir du thread d'où je l'appelle.

    En somme j'ai une classe qui fait l'interface (Interf.cs) entre ma librairie TCP, et l'UI pour chaque client.
    L'application démarre sur ma fenêtre principale Global.cs et crée un objet Interf, qui lui s'occupe de démarrer l'écoute TCP, la réception des clients.
    Et je pense que c'est à ce moment-là où cela va engendrer une future erreur, chaque fois qu'un client se connecte je prépare les UI sans les afficher, mais elles sont crées dans le thread de la librairie TCP (Quand le Callback EndAccept cela déclenche un event NewConnection et c'est là que je crée les fenêtres).

    Du coup, dans ce que je comprends de l'erreur, je ne pourrai quasiment rien faire, pourquoi je peux accéder et modifier n'importe quelle partie du formulaire, mais que l'affichage d'un TSMI supplémentaire fait planter ?

Discussions similaires

  1. Thread : Operation inter-threads non valide
    Par conan76 dans le forum VB.NET
    Réponses: 13
    Dernier message: 14/05/2015, 22h50
  2. Operation inter thread
    Par anatw73 dans le forum VB.NET
    Réponses: 2
    Dernier message: 03/02/2011, 02h33
  3. Erreur : Opération inter-threads non valide
    Par cadeau dans le forum C++/CLI
    Réponses: 1
    Dernier message: 12/12/2006, 09h07
  4. communication inter-thread en c sous linux
    Par splinternabs dans le forum POSIX
    Réponses: 17
    Dernier message: 22/02/2006, 09h34
  5. Réponses: 2
    Dernier message: 31/10/2005, 14h29

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