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 :

Opérations inter-threads entre deux classes


Sujet :

VB.NET

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 7
    Par défaut Opérations inter-threads entre deux classes
    Bonjour à tous,

    J'ai créé un programme dans lequel je souhaiterais lancer les calculs de plusieurs modèles simultanément sur plusieurs threads. Pour cela j'utilise un MainForm qui gère l'affichage utilisateur et une classe Modèle à partir de laquelle sont instanciés mes modèles. J'aimerais que chaque modèle puisse effectuer ses calculs sur son propre thread, et pouvoir en même temps récupérer les informations de ces calculs sur ma MainForm.

    Pour l'instant, mon code est le suivant :

    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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    Imports System.Threading
     
    'Interface utilisateur
    Public Class MainForm
        Inherits Form
     
        Public Label1 As Windows.Forms.Label
        Public Label2 As Windows.Forms.Label
     
        Private Sub MainForm_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
     
            Dim monModele1 As New Modele(Label1)
            Dim monModele2 As New Modele(Label2)
            '...
     
        End Sub
     
    End Class
     
    'Modèle de calcul
    Public Class Modele
     
        Delegate Sub ChangeTextDelegate(ByVal text As String)
        Private m_Thread As Thread
        Private m_Label As Windows.Forms.Label
     
        Public Sub New(ByVal Label As Windows.Forms.Label)
            m_Label = Label
            m_Thread = New Thread(AddressOf Calcul)
            m_Thread.Start()
        End Sub
     
        Public Sub Calcul()
            'mes gros calculs
            Dim i As Integer = 0
            Do
                i += 1
                MainForm.Invoke(New ChangeTextDelegate(AddressOf ChangeText), "Itération " & i)
                Thread.Sleep(100)
            Loop While i < 100000
        End Sub
     
        Public Sub ChangeText(ByVal text As String)
            m_Label.Text = text
        End Sub
     
    End Class
    Seulement quand j'exécute ce code, j'ai une erreur au niveau de la ligne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MainForm.Invoke(New ChangeTextDelegate(AddressOf ChangeText), "Itération " & i)
    qui me dit :

    Une erreur s'est produite lors de la création du formulaire.
    Pour plus d'informations, consultez Exception.InnerException.
    L'erreur est : Impossible d'instancier le contrôle ActiveX '8856f961-340a-11d0-a96b-00c04fd705a2',
    car le thread actuel n'est pas un thread cloisonné (STA, Single-Threaded Apartment).
    Y-a-t-il une solution pour résoudre ce problème ou est-il impossible d'effectuer des opérations inter-threads entre deux classes ?

    Merci !

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

    Il est évidemment possible de partager les infos d'une classe entre N threads, aucun souci, le problème ne vient pas de là. La mention de Single Thread Apartment se réfère aux threads STA/MTA, des notions spécifiques à COM (Comportment Object Model, le précurseur de dotnet).

    Je ne vois pas du tout pourquoi ça foire, d'autant que le GUID ActiveX que tu nous donnes est celui du contrôle utilisé pour afficher des pages web (et qui s'appuie sur un composant COM). A mon avis tu oublies un truc dans le code que tu nous as donné, essaierais-tu d'initialiser un tel contrôle depuis tes threads enfants ?

    Quoi qu'il en soit, essaye ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    m_Thread = New Thread(AddressOf Calcul)
    m_Thread.SetApartmentState(ApartmentState.STA)
    m_Thread.Start()
    Sinon, essaye tout simplement d'exécuter ton code plus tard, au moment où la Form est affichée plutôt qu'à son initialisation. Enfin, quand tu relaies une exception faisant référence à une InnerException, donne-la s'il te plaît.

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 7
    Par défaut
    Bonjour,

    Effectivement pour simplifier les choses je n'ai pas donné l’intégralité de mon code. Ma MainForm contient en effet un WebBrowser. Si je supprime ce WebBrowser, cette erreur disparaît bien, mais une autre survient :

    L'exception System.InvalidOperationException n'a pas été gérée
    Impossible d'appeler Invoke ou BeginInvoke sur un contrôle tant que le handle de fenêtre n'a pas été créé.
    J'ai exactement cette même nouvelle erreur si je laisse mon contrôle WebBrowser et que j'ajoute comme suggéré

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    m_Thread.SetApartmentState(ApartmentState.STA)
    Pour que mon code fonctionne j'ai donc ajouter
    dans la sub InitializeComponent() de ma MainForm, ce qui ne produit plus d'erreur.

    En revanche, je n'arrive pas bien à saisir pourquoi le seul fait d'avoir un WebBrowser sur ma Form provoquait la première erreur...

    Merci !

  4. #4
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    Je pense que lorsque tu as tenté d'appeler Invoke la première fois, le contrôle a été partiellement initialisé par une sorte d'initialisation paresseuse (lazy init), ce qui a causé la création du browser et la première exception. Une fois le web browser supprimé, l'initialisation partielle a été complétée, puis la méthode a réalisé que l'initialisation n'était pas totale.

    Maintenant, si ta solution fonctionne, pourquoi pas mais es-tu sûr que créer le handle prématurément ne causera pas de problèmes, ne serait-ce qu'en cas de futures modifications ? La seconde solution que j'avais proposé (créer les threads lorsque le formulaire est montré plutôt qu'à son initialisation) me semble plus sûre.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Débutant] Opération inter-Thread + inter-Class
    Par Orci76 dans le forum VB.NET
    Réponses: 2
    Dernier message: 03/05/2012, 09h59
  2. Association entre deux classes en dotnet
    Par lulu3111 dans le forum C++/CLI
    Réponses: 4
    Dernier message: 18/04/2007, 21h15
  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. Passage d'un objet entre deux classes
    Par ericlemoustic dans le forum Langage
    Réponses: 2
    Dernier message: 13/10/2006, 09h58
  5. Réponses: 5
    Dernier message: 17/08/2005, 12h40

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