2012-09-21 167 views
5

截止形式我有一個WinForms應用程序,它由一個主UI線程和4個任務。我的主要形式有這樣一個私有成員級別的變量:與任務運行

private bool keepThreadsRunning = false; 

在我的主要形式的Load()事件,我有以下幾點:

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()); 

裏面我的每個DoStuff的()方法,我基本上有這樣的:

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

最後,在我的Form_Closing()事件處理程序,我有以下幾點:

keepThreadsRunning = false; 
this.Close(); 

看着我在任務管理器應用程序,看來,當我閉上形式,但我有點困惑的四個任務的過程已經結束。我的調用this.Close()真的導致這些任務終止(即使它們在Thread.Sleep()調用時)?有沒有比我現在編碼的方式更好的完成此方法?

編輯 - 我簡單看了一下任務取消(當我的應用程序退出),但我的理解是,我的任務就需要定期檢查取消標記以確定它們是否已取消。因爲我的一些任務需要每30秒運行,我無法弄清楚如何我實現一個30秒等待(目前的Thread.Sleep()),並且仍然有任務來檢查取消標記。

回答

2

首先,關閉主UI線程會終止你的其他任務。如果您需要它們繼續運行,可以考慮在單獨的控制檯應用程序或Windows服務中運行它們。

即使您在完成運行所需的運行方法時發現延遲窗體關閉的方法,只有當最終用戶以您想要的方式關閉了窗體並且Windows在那裏Windows是一百萬種和一種關閉應用程序的方式,所以不能保證這會起作用。

對於運行方法異步秒每x量,你可以只用一個定時器整個事情,就像這樣:

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

而不是使用一個布爾和Thread.Sleep(),使用WaitHandle,特別是ManualResetEvent,這樣創建:

var threadTerminationHandle = new ManualResetEvent(false); 

在你的線程:

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

這將等待WaitHandle的設置,或30秒過去,以較早者爲準。

在您的形式:

所有的
threadTerminationHandle.Set(); 
Close(); 
2

當您關閉應用程序,任務將暫時關閉,因爲任務處理下後臺線程從線程池。所以,你不需要定期檢查取消標記以確定他們是否已經取消