我有 2 个计时器(System.Timers.Timer)正在运行,两个计时器 Elapsed-Events 都订阅了委托。两种方法(在订阅的委托中)都在处理相同的对象(例如列表和列表中的对象)。
假设同时调用了计时器 Elapsed-Events 。
代表会在不同的线程中运行吗?还是会一个接一个的叫?我应该使代码线程安全并使用锁吗?
我有 2 个计时器(System.Timers.Timer)正在运行,两个计时器 Elapsed-Events 都订阅了委托。两种方法(在订阅的委托中)都在处理相同的对象(例如列表和列表中的对象)。
假设同时调用了计时器 Elapsed-Events 。
代表会在不同的线程中运行吗?还是会一个接一个的叫?我应该使代码线程安全并使用锁吗?
我假设您指的是System.Timers.Timer而不是System.Windows.Forms.Timer。正如文档所说:
基于服务器的 Timer 设计用于多线程环境中的工作线程。服务器计时器可以在线程之间移动以处理引发的 Elapsed 事件,从而在按时引发事件方面比 Windows 计时器更准确。
没有什么可以保证两个不同的线程不会Elapsed
为两个不同的计时器引发事件。最好让你的代码线程安全。
我正在添加一个简短的代码片段,以显示Elapsed
可以同时调用多个回调(在这种情况下,导致死锁 -Debug.WriteLine
永远不会调用)。
var _lock = new object();
GC.KeepAlive(_lock);
var timer1 = new Timer(100);
var timer2 = new Timer(200);
timer1.Elapsed += delegate
{
lock (_lock)
Thread.Sleep(-1);
};
timer2.Elapsed += delegate
{
lock (_lock)
Debug.WriteLine("Hello world.");
};
timer1.Start();
timer2.Start();
它们将作为工作项在 ThreadPool 中排队,因此,是的,它们存在并发执行的风险。确保不会发生这种情况的一种方法是仅安排单个计时器回调和无限循环时间(支持System.Threading.Timer
这一点),并在工作完成时重新安排。
计时器回调(您没有指定特定的类/命名空间)总是在单独的线程中调用。所以你应该让你的代码线程安全。它们是否会被“同时”调用或随后被调用取决于它们的间隔设置。
使用相同的间隔集,首先调用哪个回调几乎是不确定的。