2011-06-06 1 views
0

J'ai une classe qui gère une action en temps réel dans un thread qu'il commence. Il y a d'autres thèmes en jeu dans cette application car il est très complexe. Quand cette action commence, je dois ouvrir une fenêtre et la fermer quand c'est fait. Cela semble facile.Threads UI et les cauchemars

Il existe des événements auxquels je me connecte lorsque cette action démarre et s'arrête. Dans ces gestionnaires d'événements, je place le code:

 private void Voice_SpeakStarted(object sender, TMSpeakStartedEventArgs e) 
    { 

     InfoWindow = new Form(); 
     InfoWindow.Show(); 
    } 

    /// <summary> 
    /// this is the event handler speaking stops 
    /// </summary> 
    /// <param name="sender"></param> 
    /// <param name="e"></param> 
    private void Voice_SpeakCompleted(object sender, TMSpeakCompletedEventArgs e) 
    { 
     if (InfoWindow.InvokeRequired) 
     { 
      InfoWindow.Invoke(new Action(() => 
      { 
       InfoWindow.Close(); 
      })); 

      InfoWindow.Hide(); 
     } 
    } 

Il y a des fois où j'obtiens une erreur que le thread s'est terminé. (Une erreur s'est produite lors de l'appel de la méthode Le thread de destination n'existe plus.)

Je semble toujours avoir la fenêtre à afficher. Je n'arrive pas à fermer la fenêtre.

Je vois aussi que parfois le gestionnaire ne s'appelle pas lui-même.

J'ai besoin d'aide. Je peux poster plus de code s'il serait utile.

Modifié - ajouté plus de code Voici comment je commence la classe

 public void start() 
    { 
     //It's already alive, nothing to do 
     if (alive) return; 

     //Make sure this is the only place where alive is set to true 
     alive = true; 

     Voice.SpeakCompleted += new Speech.TMSpeakCompletedDelegate(Voice_SpeakCompleted); 
     Voice.SpeakStarted += new Speech.TMSpeakStartedDelegate(Voice_SpeakStarted); 


     dispatch = new Thread(new ThreadStart(ProcessSayList)); 
     dispatch.Start(); 
    } 

Le constructeur de la classe est

public AnimationControl(dynamic parent) 
    { 
     Parent = parent; 
     Voice = new Speech(); 

     q = Queue.Synchronized(new Queue(1000)); 
     start(); 
    } 
+0

Qu'est-ce 'ProcessSayList'? Quelle classe? Ajoutez du contexte! – Blindy

Répondre

1

Vous devriez vraiment spécialiser votre fil et cesser d'appeler le code managé par d'autres fil former un fil. Utilisez les files d'attente de messages pour communiquer les actions à votre thread. C'est la manière la plus sûre de faire du multi-threading.

Exemple en pseudo-code:

Thread1 
{ 
    while (1) 
    { 
    read my last message in my queue; 
    do something according to this message like: 
    openwindow(); 
    or closewindow(); 
    } 
} 

Thread2 
{ 
    My life is short, I just need to post a message to thread1 
} 


Thread3 
{ 
    etc. 
} 

Il existe des structures prêtes à l'emploi pour une telle chose sur tous les systèmes. Et ce faisant, il sera beaucoup plus facile de comprendre ce qui se passe en cas de problème comme celui-là. Bien sûr, si vous ne faites pas attention, votre programme fileté peut devenir absolument linéaire; le but est de s'assurer que certaines parties des actions peuvent être faites en parallèle et ne créent pas une chaîne de threads qui attendent les uns les autres, un par un :)

0

Eh bien pour une chose que vous appelez Hide sur votre fenêtre sur le thread incorrect, même si InvokeRequired renvoie la valeur true.

Je peux également deviner que vous créez votre instance Voice sur un nouveau thread et que vous revenez lorsque vous recevez un message "close", ce qui détruit parfois le thread dans lequel vous essayez d'acheminer les messages Windows. Pensez à tenir le fil jusqu'à ce que votre fenêtre soit fermée.

Et oui, vous devriez poster plus de code, il n'y a pas une seule ligne de code qui montre comment vous créez/disposer de ce fil.

+0

J'ai ajouté plus de code ci-dessus – Jeff