System.Timers.Timer vs System.Threading.Timer

我最近一直在检查一些可能的计时器,System.Threading.TimerSystem.Timers.Timer对我来说是必要的(因为它们支持线程池)。

我正在制作一款游戏,我计划使用各种类型的事件,以及不同的间隔等等。

哪一个最好?

337157 次浏览

这篇文章给出了一个相当全面的解释:

比较。net框架类库中的定时器类”-也可以使用作为.chm文件

具体的区别似乎是,System.Timers.Timer面向多线程应用程序,因此通过它的SynchronizationObject属性是线程安全的,而System.Threading.Timer却不是开箱即用的线程安全的。

我不相信这两者之间有什么区别,因为它涉及到你的间隔可以有多小。

在他的书“CLR Via c#”中,杰夫ritch不鼓励使用System.Timers.Timer,这个计时器是从System.ComponentModel.Component派生出来的,允许它在Visual Studio的设计面中使用。所以它只在你想在设计平面上设置计时器时才有用。

他更喜欢将System.Threading.Timer用于线程池线程上的后台任务。

System.Threading.Timer是一个普通定时器。它在线程池线程(从工作池)上调用您。

System.Timers.Timer是一个包装了System.Threading.TimerSystem.ComponentModel.Component,并提供了一些用于在特定线程上调度的附加特性。

相反,System.Windows.Forms.Timer包装了原生的message-only-HWND,并使用窗口计时器在HWNDs消息循环中引发事件。

如果你的应用程序没有UI,而你想要最轻量级和最通用的。net定时器(因为你很乐意自己弄清楚线程/调度),那么System.Threading.Timer是框架中最好的。

我不完全清楚System.Threading.Timer所谓的“不线程安全”问题是什么。也许和这个问题一样:System.Timers.Timer vs System.Threading.Timer的线程安全性,或者每个人的意思都是:

    当你使用计时器时,很容易编写竞争条件。请看这个问题: 李# EYZ0 < / p > < / >
  1. 计时器通知的重入,在您完成处理first事件之前,计时器事件可以触发并回叫您时间。例如,请看这个问题:使用System.Threading.Timer和Monitor线程安全执行

我从MSDN找到了一个简短的比较

.NET框架类库包括四个名为Timer的类, 每一个都提供不同的功能:

System.Timers.Timer,它触发一个事件并定期在一个或多个事件接收器中执行代码。这门课 用作多线程中的基于服务器的或服务组件 环境;它没有用户界面,在运行时不可见

System.Threading.Timer,它定期在线程池线程上执行一个回调方法。回调方法是 在实例化计时器时定义,不能更改。就像 timer类,该类用于 多线程环境中基于服务器或服务的组件;它

System.Windows.Forms.Timer,一个Windows窗体组件,它触发一个事件并定期在一个或多个事件接收器中执行代码 间隔。该组件没有用户界面,是为使用而设计的

.在单线程环境中

System.Web.UI.Timer,一个ASP。NET组件,该组件定期执行异步或同步web页面回发。

这两个类在功能上是等效的,除了System.Timers.Timer有一个选项,可以通过设置SynchronizingObject来调用ISynchronizeInvoke的所有计时器过期回调。否则,两个计时器都调用线程池线程的过期回调。

当您将System.Timers.Timer拖到Windows窗体设计面上时,Visual Studio将SynchronizingObject设置为窗体对象,这将导致在UI线程上调用所有过期回调。

System.Threading.Timer是一个简单、轻量级的定时器,它使用回调方法,由线程池线程提供服务。不建议与Windows窗体一起使用,因为它的回调不会发生在用户界面线程上。System.Windows.Forms.Timer对于Windows窗体来说是一个更好的选择。对于基于服务器的定时器功能,您可以考虑使用System.Timers.Timer,它会引发事件并具有其他特性。

Source

上面没有提到的一个重要区别是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);

来自微软的信息(见关于MSDN的说明):

    <李> # EYZ0, 在一个或多个事件接收器中触发事件并执行代码 每隔一定的时间。该类旨在用作基于服务器的类 或多线程环境中的服务组件;它没有用户 接口,在运行时不可见 <李> # EYZ0, 哪个在线程池线程上执行单个回调方法 定期。当计时器为时定义回调方法 已实例化且不能更改。比如System.Timers.Timer 类,该类旨在用作基于服务器的或服务 组件在多线程环境中;它没有用户界面
  • System.Windows.Forms.Timer . (.NET框架),一个Windows窗体组件,它会触发一个事件 并定期在一个或多个事件接收器中执行代码。 该组件没有用户界面,设计用于 单线程环境;它在UI线程上执行
  • System.Web.UI.Timer (.NET框架),一个ASP。NET组件,执行异步
  • . .
有趣的是,System.Timers.Timer在。net Core 1.0中已弃用,但在。net Core 2.0 (/ . net Standard 2.0)中再次实现。 . net标准2.0的目标是尽可能容易地从。net框架中切换,这可能是它回归的原因

当它被弃用时,.NET可移植性分析器Visual Studio插件建议使用System.Threading.Timer代替。

看起来微软更喜欢System.Threading.Timer而不是System.Timers.Timer

EDIT NOTE 2018-11-15: 我不得不改变我的答案,因为关于. net Core 1.0的旧信息不再有效

正如其他人提到的到女士文档的链接,System.Timers.TimerSystem.Threading.Timer之间的一个主要区别是System.Threading.Timer执行回调方法定义一次,而System.Timers.Timer对事件做出反应,所以支持多个订阅者,也可以删除。

如上所述,System.Timers.Timer在内部使用System.Threading.Timer,例如,Enable=false处理内部计时器,并在Enable=true / Start()上重新创建它: # EYZ0 < / p >