2012-09-21 127 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

当您关闭应用程序,任务将暂时关闭,因为任务处理下后台线程从线程池。所以,你不需要定期检查取消标记以确定他们是否已经取消