关于System.Threading.Timer和Parallel的一些问题

时间:2012-08-22 15:24:23

标签: c# .net multithreading

我想每隔x秒启动一些功能。但我不想等到任何功能,直到它再次启动我的功能。假设我将计时器设置为5秒,然后我开始functionX(),并且在5秒后functionX()未完成=>我想在一个新线程中再次启动functionX()。我也希望一组功能同时开始。

这就是为什么我认为我必须使用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,为什么不是ABC?这是正常的,输出A,B,C是以某种方式在第一次输出随机后?

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

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

我的意思是康纳尔正在开始,但是在一些毫秒之后它已经关闭并且不再开放。但它应该出现,因为我一次又一次地呼叫A,B,C,所以一个新的consol应该一次又一次出现。有任何想法吗?谢谢

2 个答案:

答案 0 :(得分:2)

main方法在创建计时器后立即返回。这就是end如此早写的原因。所有其余代码都在其他线程中执行。

您的计时器方法将三个作业发送到.NETs Parallel extensions,后者也在后台线程中执行作业。这就是为什么你没有看到像ABC这样的有序输出,而是ACB,BCA CBA等等。

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

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

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

答案 1 :(得分:1)

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

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

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