2011-01-14 4 views
0

J'écris un programme qui reçoit des données de serialport et met à jour des éléments d'interface comme textboxe, labels, etc. timer est utilisé pour envoyer une commande au périphérique fréquemment, en réponse le périphérique retourne certaines données affichées. Tout va bien. maintenant, entre si je bouge la forme principale ou la minimise alors le fil dans lequel le code de réception est en cours de sortie (comme je pense). Est-il possible que la forme principale en mouvement puisse provoquer la sortie d'un thread? Et quel pourrait être le problème dans mon programme? pourquoi la réception de données s'arrête? solution posible?Problème de sortie de thread

+2

Vous n'avez pas posté votre code. C'est la même raison pour laquelle je n'ai pas pu vous aider [la dernière fois que vous avez posé cette question] (http://stackoverflow.com/questions/4667272/receiving-data-from-serialport-stops-when-main-form-is- minimisé-ou-déplacé). –

+1

Peut-être poster un aperçu de votre code? –

Répondre

0

Vos comportements (déplacer/minimiser le formulaire) n'affecteront pas les threads créés dans le code dans la plupart des cas. Le thread de données mettant à jour l'interface utilisateur (peut-être utiliser quelque chose comme myControl.Invoke) fonctionnera bien même si vous déplacez le formulaire ou minimisé le formulaire (mais si vous fermez le formulaire sans le thread de mise à jour abandonné, vous obtiendrez des exceptions). Donc, vous ne devriez pas vous inquiéter à ce sujet. Au lieu de cela, je pense que vous devez vérifier le code derrière l'événement en mouvement ou l'événement minimisé de votre formulaire. Fournir du code est utile pour trouver la raison.

0

Il existe une fenêtre de débogage appelée Threads. Démarrez votre programme et ouvrez la fenêtre des discussions lorsqu'un point d'arrêt est atteint. Lorsque votre thread reçoit des données, il doit y avoir au moins deux identifiants de thread listés, le thread de l'interface utilisateur et le thread recevant et recevant les données série. Vous voudrez peut-être NAME votre thread afin qu'il soit plus facile à voir dans le débogueur, sinon il y aura juste des identifiants de threads. De là, cela devrait donner des indices sur pourquoi ou au moins quand il sort.

Placez des points d'arrêt dans votre code de thread ainsi que votre code d'interface utilisateur à surveiller. La question est assez vague, mais le débogage et l'observation des discussions devraient aider.

1

Vous mettez à jour les éléments de l'interface utilisateur dans le thread de récupération. Cela signifie que vous devez appeler l'appel de mise à jour de l'interface utilisateur sur les contrôles, car ils ne sont pas créés dans un autre thread.

, je devine que recepteur fonctionne comme suit:

while(!Application.IsApplicationExiting) 
{ 
    if (!serial.IsReady) break; 
    ... 
    Data data = serial.GetData(); 
    string text = GetBaudRate(data); 
    ui.Invoke((Label label) => label.Text = value, txtBauldRateLabel); 
    ... 
} 

À l'époque, il faut savoir que dans ce cas ce fil sont bloqués, jusqu'à ce que l'appel à des fins de thread d'interface utilisateur, mais interesing partie est les mises à jour du thread de l'interface utilisateur se bloquent également lorsque vous essayez de redimensionner ou positionnez la fenêtre de l'application.

Votre thread d'interface utilisateur bloque lorsque vous essayez de cliquer et maintenez pendant un moment le bouton droit de la souris sur une petite barre de votre application. Donc, vous avez un verrou sur le cycle principal d'un récepteur qui ne peut en fait être bloqué en cas de timeout sur un périphérique, ce qui déclenche l'arrêt d'un récepteur (change l'état de la série en non prêt).

conseils que je vous réécrire votre application en utilisant l'appel à BeginInvoke débouchage():

while(!Application.IsApplicationExiting) 
{ 
    ... 
    ui.BeginInvoke((Label label) => label.Text = value, txtBauldRateLabel); 
    ... 
} 
0

Vous écraser le fil de la minuterie parce que vous mettez à jour les contrôles de formulaire directement à partir ... vous pouvez » Je fais ça! Vous devez appeler Invoke() pour que votre code s'exécute à partir du thread d'interface utilisateur principal.

J'ai posté une réponse dans votre autre question ... voilà à nouveau:


Je pense que vous êtes plantage de votre fil de minuterie, parce que vous ne pouvez pas mettre à jour les contrôles de formulaire d'un autre thread sans problèmes ... vous devez créer un délégué qui s'exécute sous le thread principal de l'interface utilisateur.Vous faites cela en testant Form.InvokeRequired et en appelant Form.Invoke si c'est vrai.

Ce qui se passe: Votre thread minuteur met à jour les zones de texte ou d'autres contrôles sur le formulaire. Vous redimensionnez ou réduisez, et les poignées de ces contrôles de formulaire sont invalidées ... vous ne pouvez plus les utiliser. Sauf que votre thread de minuterie est toujours en cours d'exécution et essaie de les utiliser. Crash!

Un bon exemple sur les formulaires multithread est here. La partie importante est la suivante:

delegate void SetBoolDelegate(bool parameter); 

// This would be your timer tick event handler... 
void SetInputEnabled(bool enabled) { 

    if(!InvokeRequired) { 
     button1.Enabled=enabled; 
     comboBoxDigits.Enabled=enabled; 
     numericUpDownDigits.Enabled=enabled; 
    } 
    else { 
     Invoke(new SetBoolDelegate(SetInputEnabled),new object[] {enabled}); 
    } 

} 

Dans cet exemple, vous testez InvokeRequired. Si c'est faux, alors vous exécutez le thread principal de l'interface utilisateur et pouvez définir directement les propriétés du contrôle. Si c'est vrai, vous appelez Invoke(), en passant une fonction qui sera appelée à partir du thread principal de l'interface utilisateur.

Dans cet exemple, la fonction/délégué que vous appelez est la même que celle dans laquelle vous vous trouvez, mais ce n'est pas obligatoire. Mais vous pouvez lui passer le gestionnaire d'événement tick tick pour qu'il s'exécute sur le thread principal.