2013-04-10 5 views
1

J'ai cette erreur: Opération croisée pas valide: "Contrôle 'progressBar1' accédé à partir d'un thread autre que le thread sur lequel il a été créé." Je n'arrive pas à comprendre comment le réparer.C# enfilage accès à un autre thread

private void button1_Click(object sender, EventArgs e) 
    { 
     this.panel1.Visible = false; 
     this.panel2.Visible = true; 
     new Thread(ProgressBAR).Start(); 
    } 
    private void ProgressBAR() 
    { 
     Thread.Sleep(5); 
     for (int start = 0; start <= 100; start++) 
     { 
      this.progressBar1.Value = start; 
      Thread.Sleep(5); 
     } 
    } 

Répondre

2

Vous devez utiliser la méthode de barre de progression Invoke pour exécuter la tâche sur thread principal du contrôle:

this.progressBar1.Invoke((Action)() => this.progressBar1.Value = start, null); 

Vous devez seulement faire ceci quand progressBar1.InvokeRequired est vrai. Pensez à utiliser this extension class (auto-promotion éhontée, désolé à ce sujet). Ensuite, vous pouvez oublier si vous êtes sur le bon fil:

this.progressBar1.AutoInvoke(() => this.ProgressBar1.Value = start); 
3

Essayez ceci:

private void button1_Click(object sender, EventArgs e) 
{ 
    this.panel1.Visible = false; 
    this.panel2.Visible = true; 
    new Thread(ProgressBAR).Start(); 
} 

private void ProgressBAR() 
{ 
    Thread.Sleep(5); 
    for (int start = 0; start <= 100; start++) 
    { 
     this.Invoke(new Action(() => this.progressBar1.Value = start)); 
     Thread.Sleep(5); 
    } 
} 

En raison des limitations du système d'exploitation, vous ne pouvez pas accéder à un élément d'interface utilisateur de tout fil autre que le fil qu'il a été créé. L'appel à Invoke appelle de manière synchrone l'appel pour mettre à jour la valeur de ProgressBar sur le thread principal.

-1

Vous devez exécuter le délégué spécifié sur l'unité d'exécution qui possède le handle de fenêtre sous-jacent du contrôle.

Pour plus d'informations, voir Control.Invoke

Essayez ceci:

private void button1_Click(object sender, EventArgs e) 
{ 
    this.panel1.Visible = false; 
    this.panel2.Visible = true; 
    new Thread(ProgressBAR).Start(); 
} 

private void ProgressBAR() 
{ 
    Thread.Sleep(5); 
    for (int start = 0; start <= 100; start++) 
    { 
     this.Invoke(new Action(() => this.progressBar1.Value = start)); 
     Thread.Sleep(5); 
    } 
} 
+0

Merci, cela fonctionne parfaitement. – user2267264

+2

L'appel 'BeginInvoke' sans 'EndInvoke' correspondant est un bug et ** fuira la mémoire **. – cdhowie

+0

@cdhowie: édité Invoke() – KF2