我最近一直在检查一些可能的计时器,而Threading.Timer和Timers.Timer是那些看起来需要我的人(因为它们支持线程池)。
我正在制作游戏,我计划使用不同类型的活动,间隔不同等。
哪个最好?
答案 0 :(得分:346)
本文提供了相当全面的解释:
“Comparing the Timer Classes in the .NET Framework Class Library” - 也可用as a .chm file
具体差异似乎是System.Timers.Timer
面向多线程应用程序,因此通过其SynchronizationObject
属性是线程安全的,而System.Threading.Timer
具有讽刺意味的是不是线程安全的。 -the-框。
我不认为两者之间存在差异,因为它与你的间隔有多小有关。
答案 1 :(得分:153)
System.Threading.Timer
是一个简单的计时器。它会回调一个线程池线程(来自工作池)。
System.Timers.Timer
是一个包含System.ComponentModel.Component
的{{1}},并提供了一些用于在特定线程上进行调度的附加功能。
System.Threading.Timer
改为包装原生message-only-HWND并使用Window Timers在该HWND消息循环中引发事件。
如果您的应用没有用户界面,并且您想要最轻量级和通用的.Net计时器,(因为您很高兴找到自己的线程/调度),那么System.Windows.Forms.Timer
就像它进入了框架。
我还不完全清楚System.Threading.Timer
所谓的'不线程安全'问题是什么。也许它与这个问题中的问题相同:Thread-safety of System.Timers.Timer vs System.Threading.Timer,或者也许每个人只是意味着:
当您使用计时器时,很容易写出竞争条件。例如。看到这个问题: Timer (System.Threading) thread safety
计时器通知的重新发生,您可以触发计时器事件,并在完成处理第一个事件之前回拨第二时间。例如。看到这个问题:Thread-safe execution using System.Threading.Timer and Monitor
答案 2 :(得分:117)
在他的书“ CLR通过C#”中, Jeff Ritcher 不鼓励使用System.Timers.Timer
,此计时器来自System.ComponentModel.Component
,允许它用于Visual Studio的设计表面。因此,只有在设计图面上需要计时器时才会有用。
他更喜欢在线程池线程上使用System.Threading.Timer
作为后台任务。
答案 3 :(得分:32)
Microsoft提供的有关此信息(请参阅Remarks on MSDN):
- System.Timers.Timer, 它会触发事件并在一个或多个事件接收器中执行代码 定期。该类旨在用作基于服务器的 或多线程环境中的服务组件;它没有用户 界面,在运行时不可见。
- System.Threading.Timer, 它在线程池线程上执行单个回调方法 定期。定时器时定义了回调方法 实例化,无法更改。像System.Timers.Timer一样 class,此类旨在用作基于服务器或服务 多线程环境中的组件;它没有用户界面和 在运行时不可见。
- System.Windows.Forms.Timer (仅限.NET Framework),用于触发事件的Windows窗体组件 并定期在一个或多个事件接收器中执行代码。 该组件没有用户界面,设计用于 单线程环境;它在UI线程上执行。
- System.Web.UI.Timer (仅限.NET Framework),一个执行异步的ASP.NET组件 或定期间隔的同步网页回发。
有趣的是,System.Timers.Timer
已被.NET Core 1.0弃用,但在.NET Core 2.0(/ .NET Standard 2.0)中再次实现。
.NET Standard 2.0的目标是尽可能简单地从.NET Framework切换,这可能就是它回归的原因。
不推荐使用时,.NET Portability Analyzer Visual Studio Add-In建议改为使用System.Threading.Timer
。
看起来Microsoft在System.Threading.Timer
之前赞成System.Timers.Timer
。
编辑说明2018-11-15: 由于有关.NET Core 1.0的旧信息不再有效,我提交了更改我的答案。
答案 4 :(得分:30)
上面没有提到的一个可能会让你感到震惊的重要区别是System.Timers.Timer
默默地吞下异常,而System.Threading.Timer
却没有。
例如:
var timer = new System.Timers.Timer { AutoReset = false };
timer.Elapsed += (sender, args) =>
{
var z = 0;
var i = 1 / z;
};
timer.Start();
VS
var timer = new System.Threading.Timer(x =>
{
var z = 0;
var i = 1 / z;
}, null, 0, Timeout.Infinite);
答案 5 :(得分:24)
我找到了MSDN
的简短比较.NET Framework类库包含四个名为Timer的类, 每个都提供不同的功能:
System.Timers.Timer
,它会触发事件并定期在一个或多个事件接收器中执行代码。这个课程是有意的 用作多线程中的基于服务器或服务组件 环境;它没有用户界面,在运行时不可见。
System.Threading.Timer
,它定期在线程池线程上执行单个回调方法。回调方法是 定时器实例化时定义且无法更改。像 System.Timers.Timer类,此类旨在用作 多线程环境中基于服务器或服务组件;它 没有用户界面,在运行时不可见。
System.Windows.Forms.Timer
,一个Windows窗体组件,用于触发事件并在常规的一个或多个事件接收器中执行代码 间隔。该组件没有用户界面,专为使用而设计 在单线程环境中。
System.Web.UI.Timer
,一个ASP.NET组件,定期执行异步或同步网页回发。
答案 6 :(得分:1)
这两个类在功能上是等效的,除了System.Timers.Timer
有一个选项可以通过ISynchronizeInvoke通过SynchronizingObject调用所有定时器到期回调。否则,两个计时器都会在线程池线程上调用过期回调。
将System.Timers.Timer
拖到Windows窗体设计图面上时,Visual Studio会将SynchronizingObject设置为窗体对象,这会导致在UI线程上调用所有过期回调。
答案 7 :(得分:1)
来自MSDN:System.Threading.Timer
是一个简单,轻量级的计时器,它使用回调方法并由线程池线程提供服务。不建议将其与Windows窗体一起使用,因为它的回调不会发生在用户界面线程上。 System.Windows.Forms.Timer
是与Windows窗体一起使用的更好选择。对于基于服务器的计时器功能,您可以考虑使用System.Timers.Timer
,它会引发事件并具有其他功能。
答案 8 :(得分:0)
正如其他人提到的指向 MS Docs 的链接,System.Timers.Timer
和 System.Threading.Timer
之间的一个主要区别是 System.Threading.Timer
执行一个单个回调方法<强>定义一次,而 System.Timers.Timer
对事件作出反应,因此支持多个订阅者,这些订阅者也可以删除。
如上所述,System.Timers.Timer
在内部使用 System.Threading.Timer
,例如Enable=false 处理内部计时器,并在 Enable=true / Start() 上重新创建它:
https://source.dot.net/#System.ComponentModel.TypeConverter/System/Timers/Timer.cs