2012-09-21 4 views
5

Ich habe eine WinForms-Anwendung, die aus einem Haupt-UI-Thread und 4 Aufgaben besteht. Meine Hauptform verfügt über ein eigenes Mitglied Ebene Variable wie folgt aus:Schließen Formular mit laufenden Aufgaben

private bool keepThreadsRunning = false; 

Im Load() Ereignis meiner Hauptform, ich habe folgendes:

keepThreadsRunning = true; 
var task1Worker = Task.Factory.StartNew(() => DoStuff1()); 
var task2Worker = Task.Factory.StartNew(() => DoStuff2()); 
var task3Worker = Task.Factory.StartNew(() => DoStuff3()); 
var task4Worker = Task.Factory.StartNew(() => DoStuff4()); 

Innerhalb von jedem meiner DoStuff() Methoden, ich dies im Grunde haben:

while (keepThreadsRunning) 
{ 
    // do work here 
    Thread.Sleep(30000); // a couple of my tasks only need to run every 30 seconds or so 
} 

schließlich in meinem Form_Closing() Ereignishandler, habe ich folgendes:

keepThreadsRunning = false; 
this.Close(); 

Wenn ich meine Anwendung im Task-Manager beobachte, scheint der Prozess zu enden, wenn ich mein Formular schließe, aber ich bin etwas verwirrt über die vier Aufgaben. Ist mein Aufruf zu this.Close() wirklich dazu führen, dass diese Aufgaben beendet werden (auch wenn sie in der Thread.Sleep() -Aufruf sind, wenn es passiert)? Und gibt es einen besseren Weg, dies zu erreichen, als die Art und Weise, wie ich es gerade schreibe?

BEARBEITEN - Ich habe kurz die Aufgabe abgebrochen (wenn meine App beendet wird), aber mein Verständnis ist, dass meine Aufgaben das Löschungs-Token regelmäßig überprüfen müssen, um festzustellen, ob sie abgebrochen wurden. Angesichts der Tatsache, dass einige meiner Aufgaben alle 30 Sekunden ausgeführt werden müssen, konnte ich nicht herausfinden, wie ich diese Wartezeit von 30 Sekunden implementieren würde (derzeit eine Thread.Sleep()) und die Aufgabe noch immer das Löschungs-Token überprüfen lassen würde.

Antwort

2

Vor allem den Haupt-UI-Thread schließt Ihre andere Aufgaben beenden. Wenn Sie sie weiter verwenden möchten, sollten Sie sie in einer separaten Konsolenanwendung oder einem Windows-Dienst ausführen.

Auch wenn Sie eine Möglichkeit gefunden haben, das Schließen des Formulars zu verzögern, während Sie die Methoden ausführen, die ausgeführt werden müssen, funktioniert dies nur, wenn der Endbenutzer das Formular auf die von Ihnen gewünschte Weise geschlossen hat Es gibt eine Million und eine Möglichkeit, eine Anwendung zu schließen, daher gibt es keine Garantie dafür, dass dies funktioniert.

für ein Verfahren asynchron jede x Anzahl der Sekunden laufen, Sie könnten nur einen Timer für die ganze Sache verwenden, etwa so:

using System; 
using System.Timers; 
using System.Windows.Forms; 

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

     private void Form1_Load(object sender, EventArgs e) 
     { 
      var timer1 = new System.Timers.Timer { Interval = 30000, Enabled = true }; 
      var timer2 = new System.Timers.Timer { Interval = 20000, Enabled = true }; 
      var timer3 = new System.Timers.Timer { Interval = 10000, Enabled = true }; 
      var timer4 = new System.Timers.Timer { Interval = 5000, Enabled = true }; 

      timer1.Elapsed += timer1_Elapsed; 
      timer2.Elapsed += timer2_Elapsed; 
      timer3.Elapsed += timer3_Elapsed; 
      timer4.Elapsed += timer4_Elapsed; 
     } 

     void timer4_Elapsed(object sender, ElapsedEventArgs e) 
     { 
      //do work here 
     } 

     void timer3_Elapsed(object sender, ElapsedEventArgs e) 
     { 
      //do work here 
     } 

     void timer2_Elapsed(object sender, ElapsedEventArgs e) 
     { 
      //do work here 
     } 

     void timer1_Elapsed(object sender, ElapsedEventArgs e) 
     { 
      //do work here 
     } 
    } 
} 
3

eher ein boolean und Thread.Sleep() als verwenden, verwenden Sie eine WaitHandle, insbesondere ein ManualResetEvent, wie diese erstellt:

var threadTerminationHandle = new ManualResetEvent(false); 

In Thread:

do { 
    // do work here 
} while (!threadTerminationHandle.WaitOne(TimeSpan.FromSeconds(30)) 

Dies wird warten, bis das Waithandle gesetzt oder 30 Sekunden verstreichen, je nachdem, was früher eintritt.

In Ihrem Formular:

threadTerminationHandle.Set(); 
Close(); 
2

Beim Schließen Anwendung wird die Arbeit dementsprechend geschlossen werden, weil Aufgabe verarbeitet wird unter Hintergrund Thread aus Thread-Pool. Daher müssen Sie das Löschungs-Token nicht regelmäßig überprüfen, um festzustellen, ob es abgebrochen wurde

Verwandte Themen