2010-12-12 90 views
0

Ce bug m'a poussé à passer 4 heures à déboguer du code parfaitement fonctionnel hier soir.Pourquoi le même code vide-t-il une étiquette mais modifie avec succès la propriété text d'un bouton en C#?

Fondamentalement, dans certaines situations, C# ne met pas à jour le texte d'une étiquette de texte, mais l'efface.

Je vais vous donner la configuration. Le code que j'écris met actuellement à jour une étiquette de texte avec des chaînes diffusées sur une connexion réseau. Comme il provient d'une connexion réseau, il vient aussi d'un thread d'arrière-plan, donc je dois utiliser Control.Invoke.

Si: J'envoie une ou deux chaînes mises à jour très bien. Je lui dis de mettre les données de la chaîne sur la propriété de texte d'un contrôle de bouton, il le fait très bien. Peu importe à quelle vitesse il entre.

Cependant, il ne s'affiche pas sur les étiquettes s'il arrive trop vite. Le texte de l'étiquette est masqué à la place, mais occasionnellement, je vais voir de brefs flashs de données. J'ai essayé de lire la propriété de texte d'étiquette à partir d'autres contrôles et il est en fait effacé du texte, pas simplement l'affichage de rien. L'arrêt du flux de données le laisse vide.

Voici le code actuel si cela vous aide.

//oncreate event 
public debugScreen() { 
InitializeComponent(); 

//used incase guiUdater is ran from the wrong thread 
guiupdate = new guiUpdateDelegate(guiUpdaterFromBackgroundThread); 
} 

//delegate and creation defininiton for above 
private delegate Delegate guiUpdateDelegate(Int32 location, string labelText); 
guiUpdateDelegate guiUpdate; 


//updates the form control 
public void guiUpdater(string labelName, string labelText) { 

//gets theindex psoition of the control in the form's Control array, returns -1 if not found 
Int32 location = findControlIndexNumberFromName(labelName); 

//if the item is found 
if (location >= 0) { 

    //if this function was invoked from the wrong thread 
    if (this.Controls[location].InvokeRequired) { 

    //invoke the delagate with the function to handle gui updating from the corrext thread. 
    //location is the index number of the array in the form's Control array 
    //labelText is the new value for the label 
    this.Controls[location].Invoke(guiupdate, location, labelText); 
    } 
    else { 

    //if in correct thread just update the bloody thing 
    this.Controls[location].Text = labelText; 
    } 
} 
else { 
    //if control was not found (location = -1) redo with error on label 9 
    guiUpdater("Label9","not found: " + labelName); 
} 
} 

//updates the text label 
private Delegate guiUpdaterFromBackgroundThread(Int32 location, string labelText) { 
Controls[location].Text = labelText; 
return null; 
} 

Il ne fait pas quelque chose d'essentiel, juste sortie de débogage, et car il met à jour très bien sur les boutons je sais que les données sont en train de passer. Donc, si c'est la limite de ce problème, je peux vivre avec. Cependant, je suis assez curieux de savoir ce qui se passe. On dirait qu'il pourrait être en train de couper au milieu de la mise à jour de l'étiquette. Comme si le libellé était bloqué, puis que vous appliquiez un nouveau texte, mais que vous vous arrêtiez juste au milieu avant la nouvelle partie de texte.

Si tel est le cas, il pourrait être un avertissement d'un bug méchant plus tard si je ne l'étouffe pas dans l'œuf.

Certains conseils ont essayé d'ajouter Application.DoEvents() et Refresh() aux parties pertinentes du code. Toujours eu le même problème. Après avoir lu la documentation de la méthode DoEvents(), je ne pense pas que ce soit un problème. Ça devrait être le feu tout seul.

En lisant la documentation j'ai essayé de substituer BeginInvoke, mais le même problème. Et BeginInvoke semble dangereux quand même.

+0

'Application.DoEvents()' n'est utile que si vous passez beaucoup de temps sur le thread graphique - vous êtes donc là. –

Répondre

2

Je ne suis pas sûr de pouvoir répondre POURQUOI cela se produit, mais si les données arrivent si rapidement, est-il utile de mettre à jour l'interface utilisateur pour chaque mise à jour? Qui peut le lire quand même? Que diriez-vous de le mettre en mémoire tampon, comme mettre la dernière mise à jour dans une sorte de structure de données, et quand un certain temps coïncide, mettre à jour l'interface utilisateur avec la dernière valeur dans cette structure de données.

+0

Rx (les extensions réactives) sont idéales pour ce type de tampon. Rx contient également (commodément) des méthodes d'abonnement sur le bon thread, ce qui vous évite d'écrire le contenu de 'InvokeRequired'. –

+0

Eh bien les données sont un ensemble de coordonnées de pixels x et y prises à partir de l'emplacement tactile d'un téléphone à écran tactile envoyé sur une connexion réseau à l'ordinateur. Cela ne change pas grand chose, mais l'écran tactile est un peu nerveux et il fluctue constamment de 1 ou 2 pixels. Fondamentalement, les deux premiers chiffres sont facilement lisibles. – netsplit

+0

Je vais regarder dans la chose tampon, merci! – netsplit