2010-02-12 5 views
6

Questo è il mio primo post su questo sito, che devo dire, ottimo!Aggiungi un controllo su un modulo, da un altro thread

Bene, ecco il mio problema, e spero davvero che qualcuno possa aiutarmi.

Stavo cercando di rimandare l'aggiunta di controlli al mio modulo principale, con l'obiettivo di accelerare il suo orario di inizio. Beh, ho eseguito nel seguente eccezione:

operazione cross-thread non valida: controllo 'Form1' si accede da un thread diverso dal thread è stato creato on.

Ho tentato semplicemente il problema su un esempio più piccolo ma il problema rimane. Qui è il mio codice:

using System; 
using System.Drawing; 
using System.Threading; 
using System.Windows.Forms; 

namespace AddConrolFromAnotherThread { 
    public partial class Form1 : Form { 

     public Form1() { 
      InitializeComponent(); 
     } 


     private void AddButton() { 
      if(this.InvokeRequired){ 
       this.Invoke(new MethodInvoker(this.AddButton)); 
      } 
      Random random = new Random(2); 
      Thread.Sleep(20); 
      Button button = new Button(); 
      button.Size = new Size(50,50); 
      button.Location = 
       new Point(random.Next(this.Width),random.Next(this.Height)); 
       this.Controls.Add(button); 
     } 

     private void buttonStart_Click(object sender, EventArgs e) { 
      Thread addControlThread = 
       new Thread(new ThreadStart(this.AddButton)); 
      addControlThread.Start(); 
     } 
    } 
} 

ho usato il metodo Invoke e fatto controllare se InvokeRequiered è vero, ma InvokeRequiered continuo a stare "vero". Non lo capisco davvero. Almeno mi aspetterei eccezione StackOverflow, poiché si tratta di una chiamata di ricorsione.

Quindi, se qualcuno ha incontrato il problema simile, per favore potresti dirmi cosa ho fatto di sbagliato?

Grazie, Igor!

risposta

4

Il problema nel codice è che il vostro stanno aggiungendo due pulsanti.

Inserire il codice dopo il blocco if in un altro blocco.

private void AddButton() { 
     if(this.InvokeRequired){ 
      this.Invoke(new MethodInvoker(this.AddButton)); 
     } 
     else { 
      Random random = new Random(2); 
      Thread.Sleep(20); 
      Button button = new Button(); 
      button.Size = new Size(50,50); 
      button.Location = new Point(random.Next(this.Width),random.Next(this.Height)); 
      this.Controls.Add(button); 
     } 
    } 
0

Utilizzare invece metodi anonimi. La spiegazione è sotto.

Se abbiamo forma in questo modo:

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void Form1_Load(object sender, EventArgs e) 
    { 
     Thread t = new Thread(new ThreadStart(Start)); 
     t.Start(); 
    } 

    private void UpdateText() 
    { 
     button1.Text = "New Text"; 
    } 

    void Start() 
    { 
     UpdateText(); 
    } 
} 

Questo sarà un'eccezione.

Cambio UPDATETEXT a:

private delegate void MyDelegate(); 

private void UpdateText() 
{ 
    if (button1.InvokeRequired) 
    { 
     button1.Invoke(new MyDelegate(UpdateText)); 
    } 
    button1.Text = "New Text"; 
} 

o utilizzare metodo anonimo:

void Start() 
{ 
    this.Invoke((MyDelegate)delegate 
    { 
     UpdateText(); 
    }); 
} 

private void UpdateText() 
{ 
    button1.Text = "New Text"; 
} 
+0

Ciao, Sash. Grazie per una rapida risposta. Ma non sono sicuro che ci capiamo. Ho controllato se il modulo richiede la chiamata Invoke. E nel mio caso non aggiorno un controllo, sto solo cercando di aggiungerne uno nuovo nel modulo. – Gico

+0

La differenza non è così grande - devi creare il controllo che vuoi aggiungere nello stesso thread di Form (dopo InitializeComponent per esempio) e poi aggiungerlo dal thread separato usando gli approcci che ho descritto. – sashaeve

0

È molto costoso utilizzare una discussione per aggiungere semplicemente un pulsante! Utilizzare invece il ThreadPool.