2012-08-22 42 views
0

我想每x秒启动一些函数。但是我不想等任何函数,直到它在我再次启动函数之前完成。假设我将计时器设置为5秒,并且我开始functionX(),5秒后functionX()未完成=>我想在新线程中再次启动functionX()。我也希望一组功能在同一时间开始。有关System.Threading.Timer和Parallel的一些问题

这就是为什么我认为我必须使用System.Threading.TimerParallel让我们写一个简单的例子,我觉得这是应该的:

class Program 
    { 
     private static System.Threading.Timer timer; 
     private static int interval = 2000; 

     static void Main(string[] args) 
     { 
      Console.WriteLine("go"); 
      Run(); 
      Console.WriteLine("end"); 
      Console.ReadKey(); 
     } 

     private static void Run() 
     { 
      timer = new System.Threading.Timer(TimerCallback, null, 0, interval); 
     } 

     private static void TimerCallback(Object o) { 
      Parallel.Invoke(() => FunctionA(),() => FunctionB(),() => FunctionC()); 
     } 

     private static void FunctionA() 
     { 
      Console.WriteLine("A"); 
     } 

     private static void FunctionB() 
     { 
      Console.WriteLine("B"); 
     } 

     private static void FunctionC() 
     { 
      Console.WriteLine("C"); 
     } 
    } 

这是好吗?有什么建议么?即使这个代码是有点不对:我想请教一下我的输出另一个问题 - 如果我开始这个代码我得到这样的输出:

go 
end 
A 
B 
C 
C 
A 
B 
C 
A 
B 
C 
B 
A 

嗯。第一个输出go很好,但为什么第二个是end,为什么不是AB,C?这是正常的,即输出A,B,C在第一个输出随机后以某种方式?

接下来的问题我不明白:如果我删除行Console.ReadKey();我看不到任何输出。

 static void Main(string[] args) 
     { 
      Console.WriteLine("go"); 
      Run(); 
      Console.WriteLine("end"); 
     } 

我的意思是控制台启动,但一些millisec后,它关闭,它不能再次打开。但它应该出现,因为我一次又一次地呼叫A,B,C,所以一个新的控制台应该一次又一次地出现。有任何想法吗?谢谢

+1

新线程异步启动,不要停止当前线程继续运行,甚至退出,这会停止所有子线程。 – mellamokb

回答

2

定时器创建后立即返回主方法。这就是为什么end写得这么早。所有其他代码都在其他线程中执行。

您的计时器方法将三个作业发送给.NET并行扩展,它们也在后台线程中执行作业。这就是为什么你看不到像ABC这样的有序输出,而是ACB,BCA CBA等等。

所以你有一个主线程,一个定时器后台线程和最多三个工作线程的输出(取决于你的CPU)。

Console.ReadKey()使邮件线程等待键盘输入。在此期间,其他线程可以处理他们的工作。当您删除ReadKey调用时,您的程序在写入end后立即结束,并且不会等待其他线程完成。

更改您的代码不仅要写入开始,结束和ABC,还要将Thread.CurrentThread.ManagedThreadID添加到输出。然后你可以看到哪个线程运行哪个方法。

1

并行(和其他类似的框架)不保证启动的任务(线程)的执行顺序。如果你想保证执行顺序是“A,B,C”,你可以把它们放到函数中,然后在线程中执行。

另一方面,从“主”中退出会中断正在运行的线程。典型的服务必须无限循环,直到达到退出条件(用户按ESC,接收信号,等等)。

由于您的线程在单个应用程序中运行,因此它们将永远不会为其输出打开新的控制台窗口。