2010-02-20 4 views
3

je testais un programme que je suis en train d'écrire et je reçu ce message d'erreur: Cross-thread operation not valid: Control 'lblStatus' accessed from a thread other than the thread it was created onComment déboguer des exceptions inter-thread dans .NET?

Le code est un peu massif et je ne suis pas sûr partie est à l'origine de cette erreur d'afficher un segment plus petit. Cependant, voici quelques informations qui pourraient être utiles. Je n'utilise pas de "thread" explicitement. Je devine que quelque chose d'autre crée automatiquement plusieurs threads - j'utilise une bibliothèque d'accès matériel à distance Wii et je fais de la manipulation graphique. La trace de la pile indique qu'un appel est effectué vers un gestionnaire d'événement on change, qui appelle une fonction à l'intérieur de laquelle lblStatus est essayée pour être modifiée - mais échoue.

Je me demandais comment déboguer ces types d'erreurs. J'utilise Visual Studio 2008.

EDIT

Une chose que je tiens à préciser, je ne sais pas comment ce thread différent même venu. Comment pourrais-je même trouver ça? la source du fil différent.

+0

Le fait de ne pas attacher le débogueur Visual Studio 2008 ne vous donne aucune information? –

+0

@Moron: le débogueur me montre des informations - comme les variables de surveillance, la pile d'appels ... mais je ne suis pas sûr s'il affiche des informations sur les threads. Si c'est le cas, je ne suis pas sûr où. Si quelqu'un le fait, s'il vous plaît faites le moi savoir! – Aishwar

+1

Débogage-> Windows-> Threads. –

Répondre

4
public void SetStatus(string msg) 
{ 
    if (lblStatus.InvokeRequired) 
     lblStatus.Invoke(new MethodInvoker(delegate 
     { 
      lblStatus.Text = msg; 
     })); 
    else 
     lblStatus.Text = msg; 
} 

Le texte de votre étiquette sera mis à jour.

Pour BeginInvoke, c'est la façon dont je sais (je sais qu'il ya des implémentations plus élégantes) - mais je n'ai pas essayé dans une application multi-thread encore:

Action<string> setStatus= target.AppendText; 

void OnSomeEvent (object sender, EventArgs e) 
{ 
    IAsyncRes iares = setStatus.BeginInvoke("status message", null, null); 
    setStatus.EndInvoke(iares); 
} 

public void SetStatus(string msg) 
{ lblStatus.Text = msg; } 

Pour les différentes méthodes de la synchronisation au fil de contrôle, SnOrfus fait référence à un excellent lien. Mon exemple ci-dessus sur BeginInvoke est pas correct pour la synchronisation à l'unité d'exécution du contrôle.

En ce qui concerne ce qui est à l'origine du fil: About WiimoteChanged event

+1

+1: ou utilisez BeginInvoke si vous ne souhaitez pas bloquer le thread d'interface utilisateur. –

+0

@SnOrfus: mais seulement si vous êtes prêt à appeler EndInvoke lorsque vous avez terminé. –

+0

@dboarman: Merci pour le lien sur l'événement WiimoteChanged. Je me sens un peu plus à l'aise en sachant cela. – Aishwar

2

Vous ne pouvez pas accéder aux éléments visuels d'un autre thread que le thread principal. Vous devez utiliser Dispatcher.Invoke() pour appeler un délégué qui met à jour les éléments visuels.

Exemple:

this.Dispatcher.Invoke((Action)(() => lblStatus.Content = "Hello")); 

ou (sans lambda):

this.Dispatcher.Invoke((Action)delegate() { lblStatus.Content = "Hello"; }); 
+0

@Jake: Merci pour votre réponse. J'aurais dû clarifier, je n'utilise pas WPF, mais winforms. – Aishwar

0

Vous devez combiner l'utilisation des délégués avec vos fils ..

cédez votre méthode à un délégué et invoque ensuite le délégué via le thread.

0

Une chose que je tiens à préciser, je ne sais pas comment ce thread différent même venu

Si votre application ne multithread , le problème peut être provoqué par le processus d'hébergement Visual Studio. Le processus d'hébergement Visual Studio démarre un thread principal, puis crée un nouveau thread d'interface utilisateur sur lequel l'application est exécutée. Dans certaines circonstances, cela peut entraîner une exception d'interconnexion, par exemple when accessing Form.ActiveForm before calling Application.Run.

Si tel est votre problème, vous pouvez décocher "Activer le processus d'hébergement Visual Studio" dans l'onglet Déboguer des propriétés du projet.

Questions connexes