2010-03-29 3 views
3

Pourquoi cela ne fonctionne-t-il pas?TextBox et Thread

Le programme arrête sur: this.textBox1.Text = "(New text)";

Thread demoThread; 
private void Form1_Load(object sender, EventArgs e) 
{ 
    this.demoThread = new Thread(new ThreadStart(this.ThreadProcUnsafe)); 
    this.demoThread.Start(); 

    textBox1.Text = "Written by the main thread."; 
} 

private void ThreadProcUnsafe() 
{ 
    while (true) 
    { 
     Thread.Sleep(2000); 
     this.textBox1.Text = "(New text)";   
    } 
} 

Répondre

5

Vous devez utiliser Control.Invoke lors de l'exécution de ces opérations à partir d'un fil de fond:

private void ThreadProcUnsafe() 
{ 
    while (true) 
    { 
     Thread.Sleep(2000); 
     textBox1.Invoke(new Action(() => 
     { 
      textBox1.Text = "(New Text)"; 
     })); 
    } 
} 

Si vous écrivez du code générique qui peut être exécuté à partir d'un fil d'arrière-plan, vous pouvez également vérifier la propriété Control.InvokeRequired, dans:

if (textBox1.InvokeRequired) 
{ 
    textBox1.Invoke(...); 
} 
else 
{ 
    // Original code here 
} 
5

Dans les fenêtres, un contrôle ne peut être mis à jour par le fil qui l'a créé. Vous devez utiliser Control.Invoke pour marshall un appel de méthode au thread UI pour mettre à jour le texte.

Il existe un exemple de cela sur la page MSDN Control.Invoke.

+1

Vous pouvez utiliser la méthode this.InvokeRequired pour voir si le thread en cours d'exécution est le thread de l'interface utilisateur. Si .InvokeRequired est faux, vous pouvez mettre à jour en toute sécurité la propriété .Text du contrôle. – TLiebe

+0

Absolument - mais dans son exemple, il est nécessaire. –

2

L'accès inter-thread aux contrôles Windows n'est pas autorisé. Vous avez besoin d'un autre mécanisme moins direct, tel qu'un événement ou un passage de message.

Here's an article sur le problème Control.Invoke et pourquoi BeginInvoke est un meilleur choix en raison de moins de chance de blocage.

2

Bien que je recommande d'utiliser Invoke ou BeginInvoke (après avoir appelé InvokeRequired bien sûr), vous pouvez empêcher l'exception inter-threads tout à fait en appelant auprès de votre formulaire ou UserControl:

CheckForIllegalCrossThreadCalls = false; 

(CheckForIllegalCrossThreadCalls est une propriété statique de Control)

Si vous choisissez cette option, vous pouvez obtenir des résultats étranges prospectifs dans votre interface utilisateur.