Thread du Form manquant [Résolu]

dark_naruto25 127 Messages postés mardi 23 août 2005Date d'inscription 9 mai 2011 Dernière intervention - 15 nov. 2010 à 14:06 - Dernière réponse : captainFoyd 11 Messages postés mardi 28 septembre 2010Date d'inscription 30 avril 2012 Dernière intervention
- 17 nov. 2010 à 18:52
Bonjour à tous !

Pour mon travail, je dois faire appel à une API qui gère mon interface graphique. C'est à moi que revient la tâche de créer le "Form" principal (que j'ai fait). A un certain moment, on modifie le texte d'un bouton qui jette alors l'exception InvalidAsynchronousStateException, avec comme texte "Le thread de destination n'existe plus.".
Cet appel est fait dans un thread créé par le thread (toujours en vie au moment de l'exception) qui a instancié le Form.

Y-aurait-il une manipulation spécifique à réalisée et que j'oublie ? Par ailleurs, avant le changement de texte, l'interface semble figée.

Merci de votre attention.
Afficher la suite 

9 réponses

Répondre au sujet
captainFoyd 11 Messages postés mardi 28 septembre 2010Date d'inscription 30 avril 2012 Dernière intervention - 16 nov. 2010 à 22:57
+3
Utile
Je pense qu'il te faut effectivement une boucle de message qui écoute les messages Windows. C'est elle qui permet la mise à jour ta form, qui capte les clics et autres events.

Sur la MSDN, il y a ceci:
Application.Run(Form):
Commence à exécuter une boucle de messages d'application standard sur le thread en cours et affiche le formulaire spécifié.
Pris en charge par le .NET Compact Framework.

Par contre, la méthode d'où Application.Run(Form) est appelée doit être static et avec l'attribut [STAThread].

if faut aussi appelé explicitement Application.Exit() pour quitter l'application.

[STAThread]
public static void UneMethode()
{
leForm.Load = BackgroundInitialize;
leForm.Show();
Application.Run();
}

Je ne suis pas sur de ce code car je ne sais pas qui instancie tes classes 1 et 2. Je ne sais pas non plus comment est ton thread principal. Est-ce que c'est déjà un thread d'un programme classique ou si c'est un thread type application console.
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de captainFoyd
captainFoyd 11 Messages postés mardi 28 septembre 2010Date d'inscription 30 avril 2012 Dernière intervention - 17 nov. 2010 à 17:47
+3
Utile
En C#, il n'y a qu'un seul thread qui manipule l'interface graphique.

Pour manipuler des form à partir d'un autre thread que celui de l'IHM, il faut utiliser la méthode Invoke de l'objet graphique utilisé (ex: button.Invoke(...) ou myForm.Invoke(...)).

L'appel de la méthode Invoke permet de déposer dans la boucle de message le traitement à réaliser (ex: myTextBox.Text = "Hello").

C'est parait compliquer au niveau du code à écrire mais ça a l'avantage de séparer le code "IHM" du code "Métier".
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de captainFoyd
dark_naruto25 127 Messages postés mardi 23 août 2005Date d'inscription 9 mai 2011 Dernière intervention - 15 nov. 2010 à 14:45
0
Utile
J'ai potentiellement trouvé le problème du Thread.
J'utilisais la propriété Load du Form pour démarrer un Thread d'initialisation (qui démarrait l'interface). La méthode d'initialisation (ajoutée à Load) était aussi appelée manuellement. Du coup, j'avais deux threads (de même nom) qui modifiaient mon interface.

Bon, j'ai tout déplacé dans mon Thread principal. Je lance l'appli qui semble fonctionner jusqu'au moment où j'ai testé la réactivité de la fenêtre. Pour simuler l'initialisation, j’endors mon Thread d'init pendant 5 secondes. Pendant ces 5 secondes, il est impossible de bouger la fenêtre...
Commenter la réponse de dark_naruto25
captainFoyd 11 Messages postés mardi 28 septembre 2010Date d'inscription 30 avril 2012 Dernière intervention - 16 nov. 2010 à 17:32
0
Utile
Est-ce que tu as un exemple de code?

Est-ce que tu fait comme dans l'exemple ci-dessous?

namespace TestAppli
{
    static class Program
    {
        /// <summary>
        /// Point d'entrée principal de l'application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
            System.Threading.Thread.Sleep(5000);
        }
    }
}
Commenter la réponse de captainFoyd
dark_naruto25 127 Messages postés mardi 23 août 2005Date d'inscription 9 mai 2011 Dernière intervention - 16 nov. 2010 à 18:08
0
Utile
Merci captainFoyd pour ta réponse.
Je ne peux pas mettre mon code ici. Il est beaucoup trop gros et appartient à la société où je travailles.
Mon code ne ressemble pas au tiens. Il est évident que ton "Sleep" ne sera exécuté qu'à la fermeture de ton formulaire. Je n'utilise pas Application.Run(). Je vais essayer de synthétiser le fonctionnement actuel de mon appli.
public class Thread1
{
  public void ThreadMain()
  {
    while (...)
    {
      WaitEvent(); // une sorte de sémaphore qui appel Sleep() en attendant qu'une file se remplie
      Thread2.UneMethode(); // c'est dans cette méthode que réside le suspens !
    }
  }
}

public class Thread2
{
  public Thread2()
  {
    // Créer le Form
  }

  public void UneMethode()
  {
    // je récupère le Form créé
    leForm.Load = BackgroundInitialize; // méthode qui va lancer le second thread (thread d'init)
    // et l'affiche
    leForm.Show();
    // ici, le form s'affiche (par du code qui appartient au "framework" que j'utilise
    // le form est censé avoir une couleur de fond et une image (image qui n'est pas
    // dessinée et un carré transparent à la place)
  }

  public void ThreadMain()
  {
    // ...
    Thread.Sleep(5000);
    // ...
  }
}


Du coup, je me pose plein de question sur comment gérer mes threads vis à vis du formulaire. Est ce que le "Application.Run()" est cent pour cent obligatoire (pour la boucle des messages) ? Y-a-t-il une alternative ?

P.S. : Je précise que je travaille (malheureusement) avec le .NET Compact Framework 2...
Commenter la réponse de dark_naruto25
dark_naruto25 127 Messages postés mardi 23 août 2005Date d'inscription 9 mai 2011 Dernière intervention - 17 nov. 2010 à 10:35
0
Utile
Donc effectivement, c'est bien le Application.Run(leForm) qui manque.
J'ai trouvé sur MSDN la même méthode mais sans paramètre. Mais à la compilation, ça ne marchait pas (pas présent dans le Compact Framework). Cette méthode m'aurait été bien utile pourtant. Du coup, ça me fait modifier tout ce que j'ai déjà fait concernant l'interface graphique (problème avec le Thread propriétaire de l'interface).

Merci de m'avoir aiguillé captainFoyd.
Commenter la réponse de dark_naruto25
dark_naruto25 127 Messages postés mardi 23 août 2005Date d'inscription 9 mai 2011 Dernière intervention - 17 nov. 2010 à 13:53
0
Utile
Je viens d'effectuer les changements mais un problème persiste. J'ai une exception me disant que je ne suis pas dans le bon Thread pour manipuler l'interface graphique. Cette exception provient de framework que je ne peux pas modifier.

Je vais expliquer aussi brièvement que simplement les différents threads qui rentrent en jeux dans mon appli.

Le thread principal initialise le Thread1 puis, il appel Application.Run(leForm) (pour ne pas que Thread1 perde la main)
Le Thread1 manipule l'interface, il l'initialise et lance le Thread2 (qui ne rentre plus en compte dans mon cas)

Pour que le thread principal puisse avoir un Form initialisé, j'ai utilisé un Mutex.
L'exception est jetée depuis Thread1, donc le même thread qui a créé le Form mais pas celui qui appelle le Run().

Y-a-t-il encore une restriction point de vue thread avec ce Run() ? Je ne peux pas lancer la boucle des messages dans Thread1 qui a sa propre boucle...
Commenter la réponse de dark_naruto25
dark_naruto25 127 Messages postés mardi 23 août 2005Date d'inscription 9 mai 2011 Dernière intervention - 17 nov. 2010 à 18:48
0
Utile
Oui, je connais bien ce principe. Le truc est que je ne peux pas la mettre en oeuvre dans mon code puisque c'est le "framework" (non modifiable) qui jette l'exception.
Bon, j'ai dû modifier mon code. L'interface graphique est initialisée dans le même thread qui appelle le Run(). Ca a fait pas mal de changement, mais ça semble fonctionner (j'ai encore des soucis, mais rien à voir avec les Thread, je pense).

Merci pour tes réponses ;-)
Commenter la réponse de dark_naruto25
captainFoyd 11 Messages postés mardi 28 septembre 2010Date d'inscription 30 avril 2012 Dernière intervention - 17 nov. 2010 à 18:52
0
Utile
Bon courage
Commenter la réponse de captainFoyd

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.