Thread du Form manquant

Résolu
dark_naruto25 Messages postés 127 Date d'inscription mardi 23 août 2005 Statut Membre Dernière intervention 9 mai 2011 - 15 nov. 2010 à 14:06
captainFoyd Messages postés 11 Date d'inscription mardi 28 septembre 2010 Statut Membre Dernière intervention 30 avril 2012 - 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.

9 réponses

captainFoyd Messages postés 11 Date d'inscription mardi 28 septembre 2010 Statut Membre Dernière intervention 30 avril 2012
16 nov. 2010 à 22:57
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.
3
captainFoyd Messages postés 11 Date d'inscription mardi 28 septembre 2010 Statut Membre Dernière intervention 30 avril 2012
17 nov. 2010 à 17:47
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".
3
dark_naruto25 Messages postés 127 Date d'inscription mardi 23 août 2005 Statut Membre Dernière intervention 9 mai 2011
15 nov. 2010 à 14:45
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...
0
captainFoyd Messages postés 11 Date d'inscription mardi 28 septembre 2010 Statut Membre Dernière intervention 30 avril 2012
16 nov. 2010 à 17:32
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);
        }
    }
}
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
dark_naruto25 Messages postés 127 Date d'inscription mardi 23 août 2005 Statut Membre Dernière intervention 9 mai 2011
16 nov. 2010 à 18:08
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...
0
dark_naruto25 Messages postés 127 Date d'inscription mardi 23 août 2005 Statut Membre Dernière intervention 9 mai 2011
17 nov. 2010 à 10:35
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.
0
dark_naruto25 Messages postés 127 Date d'inscription mardi 23 août 2005 Statut Membre Dernière intervention 9 mai 2011
17 nov. 2010 à 13:53
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...
0
dark_naruto25 Messages postés 127 Date d'inscription mardi 23 août 2005 Statut Membre Dernière intervention 9 mai 2011
17 nov. 2010 à 18:48
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 ;-)
0
captainFoyd Messages postés 11 Date d'inscription mardi 28 septembre 2010 Statut Membre Dernière intervention 30 avril 2012
17 nov. 2010 à 18:52
Bon courage
0
Rejoignez-nous