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 : 37
    Localisation : France

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

    Informations forums :
    Inscription : Août 2005
    Messages : 5 183
    Points : 8 873
    Points
    8 873
    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.


  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+

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, 03h58
  2. Rafraîchir une form depuis un autre thread
    Par dens19 dans le forum C#
    Réponses: 4
    Dernier message: 23/11/2009, 23h29
  3. Réponses: 12
    Dernier message: 22/02/2007, 23h38
  4. Réponses: 5
    Dernier message: 01/06/2006, 16h18
  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, 10h31

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