2009-06-11 11 views
4

Ich habe meine Haupt-GUI von wo ich eine lange laufende Methode in einem separaten Thread starten. Nun muss ich innerhalb dieses separaten Threads eine neue Form erstellen und anzeigen. Aber wenn ich diese neue Form zeige, sind alle Kontrollen fest und das Fenster sagt "nicht reagiert".So erstellen Sie Formular aus nicht GUI-Thread C#

Welches ist die beste Lösung?

Grüße

Thomas

Antwort

4

den Code setzen, die die neue GUI in die Haupt-GUI-Klasse erstellt und dann der Haupt GUIs Invoke-Methode aufrufen, oder ein Ereignis auslösen, dass die Haupt-GUI, wenn sie wissen abonnieren um die neue GUI auszulösen. Wenn Sie Letzteres auswählen, sollten Sie unbedingt InvokeRequired verwenden, um festzustellen, ob Sie die Methode zum Erstellen der neuen GUI direkt aufrufen können oder ob Sie eine Invoke-Anweisung verwenden müssen, um zum Erstellen der neuen GUI in den GUI-Thread zurückzukehren.

0

Verwenden Sie Form.Show anstelle von Form.ShowDialog. Sie können auch eine BackgroundWorker verwenden, um gleichzeitige Aufgaben zu erledigen.

2

Sie müssen lernen, über Control.BeginInvoke/Invoke und all das bedeutet. Denken Sie daran, dass alle UI-Vorgänge im Hauptthread (UI-Thread) ausgeführt werden müssen, da dies der Thread ist, der die Nachrichtenpumpe besitzt. Sie müssen in diesen Thread zurückrufen, damit UI-Aktionen ausgeführt werden.

Hier ist ein Intro zum BeginInvoke/Invoke stuff: http://weblogs.asp.net/justin_rogers/pages/126345.aspx

Um weiter zu helfen, hier ist ein komplettes Arbeitscodebeispiel, das die Grundlagen hervorheben soll.

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

    private void button1_Click(object sender, EventArgs e) 
    { 
     var worker = new Worker(this); 
     worker.Start(); 
    } 

    public void updateLabel(int value) 
    { 
     if(label1.InvokeRequired) { // check if on UI thread 
      //If true use begin invoke to call update on UI thread 
      //this calls the anonymous delegate in the UI thread 
      //that then calls the updateLabel function again to set the label's text 
      label1.BeginInvoke(new MethodInvoker(() => this.updateLabel(value))); 
      return; 
     } 

     label1.Text = value.ToString(); 
    } 

    public void showNewForm() 
    { 
     if(this.InvokeRequired) { // check if on UI thread 
      this.BeginInvoke(new MethodInvoker(this.showNewForm)); // we need to create the new form on the UI thread 
      return; 
     } 

     var anotherForm = new Form1(); 
     anotherForm.Show(); 
    } 
} 

class Worker 
{ 
    private volatile bool stop = false; 
    private Form1 form; 

    public Worker(Form1 form) 
    { 
     this.form = form; 
    } 

    public bool Stop 
    { 
     get 
     { 
      return stop; 
     } 
     set 
     { 
      stop = value; 
     } 
    } 

    public void Start() 
    { 
     var thread = new Thread(this.work); 
     thread.IsBackground = true; 
     thread.Start(); 
    } 

    private void work() 
    { 
     int i = 0; 
     while(!stop) { 
      i++; 
      Thread.Sleep(100); 

      form.updateLabel(i); 
      if(i == 50) { 
       form.showNewForm(); // call into form 
       // can also do the invokerequired check here and create new form w/ anonymous functions 
       // however, I'd recommend keeping all the UI code in the same place. 
      } 
     } 
    } 
} 
Verwandte Themen