我已经有一个做了具体的工作System.Timers.Timer运行Windows服务。 但是,我想一些作品在同一时间运行,但在不同的线程。
有人告诉我,创造一个不同的System.Timers.Timer实例。 这个对吗? 这是工作方式并行运行?
例如:
System.Timers.Timer tmr1 = new System.Timers.Timer();
tmr1.Elapsed += new ElapsedEventHandler(DoWork1);
tmr1.Interval = 5000;
System.Timers.Timer tmr2 = new System.Timers.Timer();
tmr2.Elapsed += new ElapsedEventHandler(DoWork2);
tmr2.Interval = 5000;
将tmr1
和tmr2
在不同的线程运行,从而DoWork1
和DoWork2
可以同时运行,即同时?
谢谢!
这不是不正确。
小心。 System.Timers.Timer将开始一个新的线程为每一个经过的事件。 你会惹上麻烦,当你经过的事件处理程序耗时过长。 您的处理器将再次在另一个线程调用,即使以前调用尚未完成。 这往往会产生难以诊断的错误。 有些事情,你可以通过自动复位属性设置为false避免。 此外,一定要使用try / catch语句在事件处理程序,异常吞咽没有诊断。
多个定时器可能意味着多线程。 如果两个计时器滴答发生在(即,一个正在运行,并且另一火灾)的同时,这两个计时器回调将执行在单独的线程,均未将主线程。
要注意,虽然,定时器本身不“跑”在一个线程都非常重要。 唯一的一次,一个线程涉及的是当计时器的滴答声或经过事件触发。
在另一方面,我强烈建议您不要使用System.Timers.Timer
。 该定时器的经过事件南瓜例外,也就是说,如果有异常逃逸事件处理程序,你永远不会知道它。 这是一个错误藏起来。 您应该使用System.Threading.Timer
代替。 System.Timers.Timer
只是周围的包装System.Threading.Timer
,让您得到没有错误隐藏相同的定时器功能。
见吞咽异常是隐藏的错误获取更多信息。
将TMR1和TMR2在不同的线程运行,从而DoWork1和DoWork2可以同时运行,即同时?
一开始,是的。 然而,什么是保障双方DoWork1
和DoWork2
将在5秒内完成? 也许你知道里面的代码DoWorkX
并认为他们将在5秒的时间间隔内完成,但它可能发生的系统负载下的项目之一的时间超过5秒。 这将打破你的假设,即既DoWorkX
将在随后的蜱同时启动。 在即使你以后的启动时间将是同步的这种情况下,有重叠的当前工作的执行与这仍然是从最后一跳运行工作执行的危险。
如果禁用/启用各种计时器内DoWorkX
,但是,你的开始时间会走出同步的相互-最终可能他们能获得计划在同一个线程另一个之后。 所以,如果你是OK - 以后的启动时间可能不同步 - 那么我的答案在这里结束。
如果不是,这是你可以尝试:
static void Main(string[] args)
{
var t = new System.Timers.Timer();
t.Interval = TimeSpan.FromSeconds(5).TotalMilliseconds;
t.Elapsed += (sender, evtArgs) =>
{
var timer = (System.Timers.Timer)sender;
timer.Enabled = false; //disable till work done
// attempt concurrent execution
Task work1 = Task.Factory.StartNew(() => DoWork1());
Task work2 = Task.Factory.StartNew(() => DoWork2());
Task.Factory.ContinueWhenAll(new[]{work1, work2},
_ => timer.Enabled = true); // re-enable the timer for next iteration
};
t.Enabled = true;
Console.ReadLine();
}
的种类。 首先,检查出的MSDN页面System.Timers.Timer
: http://msdn.microsoft.com/en-us/library/system.timers.timer.aspx
本节,你需要关心下面是引用:
如果物业SynchronizingObject的为空,经过的事件引发的一个线程池线程。 如果经历事件的处理持续时间超过时间间隔,该事件可能会再次在另一个线程池线程提高。 在这种情况下,事件处理程序应该是折返。
基本上,这意味着,在Timer
的动作总是会自动运行是不是使得每个Timer
都有自己的线程,而是在默认情况下,它使用系统ThreadPool
来运行的操作。
如果你想要的东西在同一时间运行(开球都在同一时间),但同时运行,你不能只是把逝去事件的多个事件。 例如,我在VS2012尝试这样做:
static void testMethod(string[] args)
{
System.Timers.Timer mytimer = new System.Timers.Timer();
mytimer.AutoReset = false;
mytimer.Interval = 3000;
mytimer.Elapsed += (x, y) => {
Console.WriteLine("First lambda. Sleeping 3 seconds");
System.Threading.Thread.Sleep(3000);
Console.WriteLine("After sleep");
};
mytimer.Elapsed += (x, y) => { Console.WriteLine("second lambda"); };
mytimer.Start();
Console.WriteLine("Press any key to go to end of method");
Console.ReadKey();
}
输出是这样的:
按任意键转到方法结束
第一拉姆达。
睡眠3秒
睡眠后
第二拉姆达
因此, 连续执行他们不能同时使用。 所以,如果你想“一堆事情发生”在每个定时器执行,你必须发射一束任务(或排队与操作线程池)在你Elapsed
处理程序。 它可以多线程他们,也可能不会,但在我的简单的例子,它没有。
自己尝试我的代码,这是相当简单说明发生了什么。