我最近一直在查看一些可能的计时器,而Threading.Timer和Timers.Timer对我来说是必要的(因为它们支持线程池)。
我正在制作游戏,我计划使用不同类型的活动,间隔不同等。
哪个最好?
本文提供了相当全面的解释:
“ 比较.NET Framework类库中的Timer类 ” - 也可用作.chm文件
具体的区别似乎是System.Timers.Timer
适用于多线程应用程序,因此通过其SynchronizationObject
属性是线程安全的,而System.Threading.Timer
具有讽刺意味的是,它不是开箱即用的线程安全的。
我不认为两者之间存在差异,因为它与您的间隔有多小有关。
System.Threading.Timer
是一个普通计时器。 它会回调一个线程池线程(来自工作池)。
System.Timers.Timer
是一个System.ComponentModel.Component
,它包装System.Threading.Timer
,并提供一些用于在特定线程上调度的附加功能。
System.Windows.Forms.Timer
改为包装本机仅消息HWND,并使用Window Timers在该HWND消息循环中引发事件。
如果您的应用程序没有UI,并且您想要最轻量级和通用的.Net计时器,(因为您很高兴找到自己的线程/调度),那么System.Threading.Timer
就像它获得的一样好框架。
我不完全清楚System.Threading.Timer
所谓的“非线程安全”问题是什么。 也许它与这个问题中的问题相同: System.Timers.Timer与System.Threading.Timer的线程安全 ,或者也许每个人只是意味着:
当你使用计时器时,很容易写出竞争条件。 例如看到这个问题: Timer(System.Threading)线程安全
计时器通知的重新进入,您的计时器事件可以触发,并在您完成第一个事件的处理之前第二次回拨您。 例如,请参阅此问题: 使用System.Threading.Timer和Monitor进行线程安全执行
我在MSDN上找到了一个简短的比较
.NET Framework类库包含四个名为Timer的类,每个类都提供不同的功能:
System.Timers.Timer
,它会定期触发事件并在一个或多个事件接收器中执行代码。 该类旨在用作多线程环境中的基于服务器或服务组件; 它没有用户界面,在运行时不可见。
System.Threading.Timer
,它定期在线程池线程上执行单个回调方法。 回调方法是在实例化定时器时定义的,无法更改。 与System.Timers.Timer类一样,此类旨在用作多线程环境中的基于服务器或服务组件; 它没有用户界面,在运行时不可见。
System.Windows.Forms.Timer
,一个Windows窗体组件,用于触发事件并定期在一个或多个事件接收器中执行代码。 该组件没有用户界面,专为在单线程环境中使用而设计。
System.Web.UI.Timer
,一个ASP.NET组件,定期执行异步或同步网页回发。
这两个类在功能上是等效的,除了System.Timers.Timer
有一个选项,通过设置SynchronizingObject来通过ISynchronizeInvoke调用它的所有计时器到期回调。 否则,两个计时器都会调用线程池线程上的到期回调。
将System.Timers.Timer
拖到Windows窗体设计图面上时,Visual Studio会将SynchronizingObject设置为窗体对象,这会导致在UI线程上调用所有过期回调。
从MSDN: System.Threading.Timer
是一个简单,轻量级的计时器,它使用回调方法,由线程池线程提供服务。 不建议将其与Windows窗体一起使用,因为它的回调不会发生在用户界面线程上。 System.Windows.Forms.Timer
是与Windows窗体一起使用的更好选择。 对于基于服务器的计时器功能,您可以考虑使用System.Timers.Timer
,它会引发事件并具有其他功能。
资源
上面没有提到的一个可能会让你感到System.Timers.Timer
重要区别是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);
Microsoft提供的有关此信息(请参阅MSDN上的备注 ):
- System.Timers.Timer ,它会定期触发事件并在一个或多个事件接收器中执行代码。 该类旨在用作多线程环境中的基于服务器或服务组件; 它没有用户界面,在运行时不可见。
- System.Threading.Timer ,它定期在线程池线程上执行单个回调方法。 回调方法是在实例化定时器时定义的,无法更改。 与System.Timers.Timer类一样,此类旨在用作多线程环境中的基于服务器或服务组件; 它没有用户界面,在运行时不可见。
- 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加载项建议使用System.Threading.Timer
。
看起来Microsoft在System.Threading.Timer
之前支持System.Timers.Timer
。
编辑说明2018-11-15:由于有关.NET Core 1.0的旧信息不再有效,我提交了更改我的答案。
在他的书“ CLR Via C# ”中, Jeff Ritcher不鼓励使用System.Timers.Timer
,这个计时器派生自System.ComponentModel.Component
,允许它在Visual Studio的设计界面中使用。 因此,只有在设计图面上需要计时器时它才有用。
他更喜欢使用System.Threading.Timer
来处理线程池线程上的后台任务。