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 :

Intéraction avec un form d'un autre thread


Sujet :

C#

  1. #1
    Rédacteur
    Avatar de Arnaud F.
    Homme Profil pro
    Développeur COBOL
    Inscrit en
    août 2005
    Messages
    5 183
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Développeur COBOL
    Secteur : Finance

    Informations forums :
    Inscription : août 2005
    Messages : 5 183
    Points : 8 870
    Points
    8 870
    Par défaut Intéraction avec un form d'un autre thread
    Bonjour,

    je fais une application de mise à jour qui est lancée avant l'application elle-même.

    Cette application est de type "Console" et je recherche si pour une taille d'écran donnée, il existe un Form contenant un Splash Screen, si oui, le charger à la place de l'affichage de la console.

    J'aimerai donc avoir mon processus de mise à jour dans un thread et l'interface dans un autre (cette dernière n'étant pas obligatoire et utilisée qu'a des fins d'affichage).

    Un premier code non threadé (qui fonctionne serait) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Assembly assembly = Assembly.LoadFrom("240x320Screens.dll");
    Form ff = assembly.CreateInstance("Screens.Loader") as Form;
    Application.Run(ff);
    // Le Form en question implémente cette interface (le contrôle est fait mais non mis ici).
    ((ISplashView)ff).SetStep("Step 1 on 3");
    Le problème est que le code est bloquant sur Application.Run();

    J'ai donc souhaité modifier ce même code en le rendant threadé, mais là c'est le drame...

    Le code :

    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
    Thread presenterThread = null;
    Assembly assembly = Assembly.LoadFrom("240x320Screens.dll");
    Form ff = assembly.CreateInstance("Screens.Loader") as Form;
     
    presenterThread = new Thread((ThreadStart)(() => 
        {
            Application.Run(ff);
        }));
    presenterThread.Start();
     
    ((ISplashView)ff).SetStep("Step 1 on 3");
    Thread.Sleep(5000);
    ((ISplashView)ff).SetStep("Step 2 on 3");
    Thread.Sleep(5000);
    ((ISplashView)ff).SetStep("Step 3 on 3");
     
    // Attend que l'utilisateur ferme l'écran (comportement voulu)
    if (presenterThread != null)
        presenterThread.Join();
    Mais ce code lève l'exception suivante :

    Control.Invoke must be used to interact with controls created on a separate thread.

    A noter que j'utilise le Compact Framework 3.5 et que les écrans sont donc en WinForms.

    C'est par l'adresse que vaut le bûcheron, bien plus que par la force. Homère

    Installation de Code::Blocks sous Debian à partir de Nightly Builds

  2. #2
    Membre habitué Avatar de monnoliv
    Homme Profil pro
    Opticien-ébéniste: lunettes de WC
    Inscrit en
    août 2003
    Messages
    139
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Opticien-ébéniste: lunettes de WC

    Informations forums :
    Inscription : août 2003
    Messages : 139
    Points : 195
    Points
    195
    Par défaut
    Lorsque tu crées une forme à partir d'une Thread, tu ne peux pas agir directement sur les contrôles affichés par la form, il y a conflit, celle-ci étant un autre thread en fait. Tu dois le faire de manière synchronisée en utilisant Invoke (pour ceux qui font du CppBuilder ça correspond à synchronize).
    Donc au lieu de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    //Dans le Thread
    ((ISplashView)ff).SetStep("Step 1 on 3");
    tu fais appel à une fonction intermédiaire qui fait appel de manière synchro à une fonction qui elle pourra modifier les contrôles:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    //Dans le Thread
    ModifieProgressionSync("Step 1 on 3");

    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
     
    private delegate void ModifieProgression(string monstr);
     
    private void ModifieProgressionSync(string monstr)
     {
      object[] args = { monstr};
      ModifieProgression Tmp = null;
     
      //AfficherSyncCB pointe sur AfficherSurFormulaire
      Tmp = new ModifieProgression(ModifieProgressionCB);
     
      //Execute ModifieProgressionCB, les paramètres sont en args.
      base.Invoke(Tmp , args);
     }
     
    //Ce n'est que ici qu'on peut modifier les contrôles d'affichage
    private void ModifieProgressionCB(string monstr)
     {
       //Modifier le contrôle
      ff.SetStep(monstr);
     }
    A+
    IoT CC3200, ESP8266
    8051, ARM Cortex-M (forever)/Cortex A (TI, Silabs, NXP), FPGA, Bare Metal Raspberry-PI programming
    VHDL-ALTERA-XILINX

Discussions similaires

  1. Un control d'une forme sur un autre thread?
    Par Eric_M dans le forum VB.NET
    Réponses: 5
    Dernier message: 25/01/2011, 04h58
  2. Rafraîchir une form depuis un autre thread
    Par dens19 dans le forum C#
    Réponses: 4
    Dernier message: 24/11/2009, 00h29
  3. Réponses: 12
    Dernier message: 23/02/2007, 00h38
  4. Réponses: 5
    Dernier message: 01/06/2006, 17h18
  5. [VS 2003][dessin] synchronizer un thread avec une forme
    Par Harry_polin dans le forum Windows Forms
    Réponses: 4
    Dernier message: 03/10/2005, 11h31

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