2010-03-09 7 views
5

Ich habe Probleme, meine GUI zu erscheinen und nicht einzufrieren, während ich einen externen Prozess (und warten auf) läuft. In diesem Fall ist drivers.exe ein sehr einfaches Programm, bei dem der Benutzer einfach auf "OK" klickt. Wenn ich auf OK klicke, wird es beendet. Ich versuche, meinen Status Strip Count Zahlen einfach (sehr schnell) zu machen, während drivers.exe ausgeführt wird. In der Praxis erscheint meine GUI jedoch nie, bis drivers.exe beendet wird.Ausführen eines anderen Prozesses ohne GUI-Einfrieren

private void run_drivers() 
     { 
      Console.WriteLine("Start Driver"); 
      int driver_timeout_in_minutes = 20; 
      System.Diagnostics.Process driverproc = System.Diagnostics.Process.Start(Application.StartupPath + "\\" + "drivers.exe"); 
      driverproc.WaitForExit(driver_timeout_in_minutes * 1000 * 60); //uses milliseconds, we must convert 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      ThreadStart worker = new ThreadStart(run_drivers); 
      Console.WriteLine("Main - Creating worker thread"); 
      toolStripStatusLabel1.Text = "hi"; 
      Thread t = new Thread(worker); 
      t.IsBackground = true; 
      t.Start(); 
      Console.WriteLine("Main - Have requested the start of worker thread"); 

      int i = 0; 
      while (t.IsAlive) 
      { 
       i++; 
       toolStripStatusLabel1.Text = i.ToString(); 
      } 
      Console.WriteLine("Dead"); 
     } 

Antwort

3

Sie in eine BackgroundWorker aussehen sollte, wie es für Sie

+0

Könnten Sie bitte zeigen Sie mir, wie? Ich habe es versucht, und es hat wirklich nicht funktioniert. Meine Form würde immer noch nicht zeigen ... überhaupt. – Adam

+2

Das Problem ist die Schleife "while (t.IsAlive)". Er muss das aus dem UI-Thread entfernen, unabhängig davon, ob er BackgroundWorker verwendet oder nicht. – Phil

2

Der Grund, dass Ihr Formular bis drivers.exe gelaufen ist zeigt nicht alle das Einfädeln Arbeit tut, ist, weil Sie drivers.exe aus laufenden innerhalb Form.Load. Form.Load tritt auf, bevor das Formular angezeigt wird. Versuchen Sie stattdessen, drivers.exe unter Form.Shown auszuführen.

Außerdem wird while(t.IsAlive) Ihren UI-Thread technisch blockieren. Wenn das nicht gewünscht ist, sollte es aus dem Hauptthread entfernt werden. Wahrscheinlich möchten Sie auch toolStripStatusLabel1.Refresh() aufrufen, um zu erzwingen, dass das Label aktualisiert wird, nachdem Sie seinen Text festgelegt haben.

+0

Ob der Code in Form.Load oder höher ausgeführt wird, der UI-Thread erhält immer noch keine Zeit, den Bildschirm zu malen, wenn er wie gezeigt ausgeführt wird. –

0

keine Schleife auf GUI-Thread. Es wird Ihre Anwendung einfrieren. Schleife muss auf Hintergrundthread sein, der toolStripStatusLabel1 durch Invoke Methode aktualisieren sollte.

siehe dieses Beispiel. ungetestet. vielleicht könnte es auch einfach so arbeiten ...

private void run_drivers() 
    { 
     Console.WriteLine("Start Driver"); 
     int driver_timeout_in_minutes = 20; 
     System.Diagnostics.Process driverproc = System.Diagnostics.Process.Start(Application.StartupPath + "\\" + "drivers.exe"); 
     int i = 0; 
     var action = new Action<int>(x => { toolStripStatusLabel1.Text = i.ToString(); }) 
     while (!driverproc.HasExited) 
     { 
      i++; 
      toolStripStatusLabel1.Invoke(action); 
     } 

     Console.WriteLine("Dead"); 
     // start another thread here... 
    } 

    private void Form1_Load(object sender, EventArgs e) 
    { 
     ThreadStart worker = new ThreadStart(run_drivers); 
     Console.WriteLine("Main - Creating worker thread"); 
     toolStripStatusLabel1.Text = "hi"; 
     Thread t = new Thread(worker); 
     t.IsBackground = true; 
     t.Start(); 
     Console.WriteLine("Main - Have requested the start of worker thread"); 
    } 
+0

Okay, das macht Sinn. Wie aber warte ich darauf, eine Funktion auszuführen, bis eine andere beendet ist? Angenommen, ich möchte func_2 erst ausführen, nachdem func_2 abgeschlossen ist. Beide werden einige Minuten dauern. – Adam

+0

starten Sie einen neuen Thread in der letzten Zeile der 'run_drivers()' Methode. Halten Sie sich einfach von Schleifen auf dem GUI-Thread fern. –

0

Eine Lösung, die Sie verwenden können, während die aktuelle Code-Struktur beibehalten wird, ist die Benutzeroberfläche in regelmäßigen Abständen auf einem timer Thread zu aktualisieren, Stoppen des Timers, wenn der Thread abgeschlossen ist. Dadurch wechseln Sie von einer Schleife zu einem ereignisgesteuerten Design, und Sie geben dem UI-Thread Zeit, Ihr Formular zu zeichnen.

// create a System.Windows.Forms.Timer through the designer or in code. 
// give it a short interval if you want the counter to increment quickly. 

int counter; 

private void Form1_Load(object sender, EventArgs e) 
{ 
    ... 
    t.Start(); 
    counter = 0; 
    timer.Start(); 
    .... 
} 

private void timer_Tick(object sender, EventArgs e) 
{ 
    if (t.IsAlive) 
    { 
     counter++; 
     toolStripStatusLabel1.Text = counter.ToString(); 
    } 
    else 
    { 
     timer.Stop(); 
    } 
} 

(ungetestet)

Verwandte Themen