.NET System.Timers.Timer的原理和使用(开发定时执行程序)
概述(来自MSDN)
Timer 组件是基于服务器的计时器,它使您能够指定在应用程序中引发Elapsed 事件的周期性间隔。然后可以操控此事件以提供定期处理。例如,假设您有一台关键性服务器,必须每周7 天、每天24 小时都保持运行。可以创建一个使用Timer 的服务,以定期检查服务器并确保系统开启并在运行。如果系统不响应,则该服务可以尝试重新启动服务器或通知管理员。
基于服务器的Timer 是为在多线程环境中用于辅助线程而设计的。服务器计时器可以在线程间移动来处理引发的Elapsed 事件,这样就可以比Windows 计时器更精确地按时引发事件。
基于Interval 属性的值,Timer 组件引发Elapsed 事件。可以处理该事件以执行所需的处理。例如,假设您有一个联机销售应用程序,它不断向数据库发送销售订单。编译发货指令的服务分批处理订单,而不是分别处理每个订单。可以使用Timer 每30 分钟启动一次批处理。
注意
当AutoReset设置为false时,Timer只在第一个Interval过后引发一次Elapsed事件。若要保持以Interval时间间隔引发Elapsed 事件,请将AutoReset设置为true。
Elapsed事件在ThreadPool线程上引发。如果Elapsed事件的处理时间比Interval长,在另一个hreadPool线程上将会再次引发此事件。因此,事件处理程序应当是可重入的。
注意
在一个线程调用Stop 方法或将Enabled 属性设置为false 的同时,可在另一个线程上运行事件处理方法。这可能导致在计时器停止之后引发Elapsed 事件。Stop 方法的示例代码演示了一种避免此争用条件的方法。
如果和用户界面元素(如窗体或控件)一起使用Timer,请将包含有Timer 的窗体或控件赋值给SynchronizingObject 属性,以便将此事件封送到用户界面线程中。Timer 在运行时是不可见的。
几点说明
1 private System.Timers.Timer _TestTimerEvent= new Timer();
1
1、默认的周期是0.1秒执行一次;
2、AutoReset的初始值为true.
3、它的timer机制和System.Threading.Timer 原理是一样的。
4、每次周期(Timer)运行一次会新起一个线程。
5、如果Elapsed事件的处理时间比Interval长,它每个周期执行都会新起一个线程,这个线程的执行时间不受interval的限定,可以比interval长,因为一个新周期执行,又会新起一个线程,Timer起的线程周期就是事件处理时间。
我们来看它的实现代码.(.net framework 提供的).
001 //------------------------------------------------------------------------------
002 // <copyright file="Timer.cs" company="Microsoft">
003 // Copyright (c) Microsoft Corporation. All rights reserved.
004 // </copyright>
005 //-----------------------------------------------------------------------------
006
007 namespace System.Timers {
008
009 using System.Runtime.InteropServices;
010 using System.Security;
011 using System.Security.Permissions;
012 using System.Threading;
013 using System.ComponentModel;
014 using System.ComponentModel.Design;
015 using System;
016 using Microsoft.Win32;
017 using Microsoft.Win32.SafeHandles;
018
019 /// <devdoc>
020 /// <para>Handles recurring events in an application.</para>
021 /// </devdoc>
022 [
023 DefaultProperty("Interval"),
024 DefaultEvent("Elapsed"),
025 HostProtection(Synchronization=true, ExternalThreading=true)
026 ]
027 public class Timer : Component, ISupportInitialize {
028 private double interval;
029 private bool enabled;
030 private bool initializing;
031 private bool delayedEnable;
032 private ElapsedEventHandler onIntervalElapsed;
033 private bool autoReset;
034 private ISynchronizeInvoke synchronizingObject;
035 private bool disposed;
036 private System.Threading.Timer timer;
037 private TimerCallback callback;
038 private Object cookie;
039
040 /// <devdoc>
041 /// <para>Initializes a new instance of the <see cref='System.Timers.Timer'/> class, with the properties
042 /// set to initial values.</para>
043 /// </devdoc>
044 public Timer()
045 : base() {
046 interval = 100;
047 enabled = false;
048 autoReset = true;
049 initializing = false;
050 delayedEnable = false;
051 callback = new TimerCallback(this.MyTimerCallback);
052 }
053
054 /// <devdoc>
055 /// <para>
056 /// Initializes a new instance of the <see cref='System.Timers.Timer'/> class, setting the <see cref='System.Timers.Timer.Interval'/> property to the specified period.
057 /// </para>
058 /// </devdoc>
059 public Timer(double interval)
060 : this() {
061 if (interval <= 0)
062 throw new ArgumentException(SR.GetString(SR.InvalidParameter, "interval", interval));
063
064 int i = (int)Math.Ceiling(interval);
065 if( i < 0) {
066 throw new ArgumentException(SR.GetString(SR.InvalidParameter, "interval", interval));
067 }
068
069 this.interval = interval;
070 }
071
072 /// <devdoc>
073 /// <para>Gets or sets a value indicating whether the Timer raises the Tick event each time the specified
074 /// Interval has elapsed,
075 /// when Enabled is set to true.</para>
076 /// </devdoc>
077 [Category("Behavior"), TimersDescription(SR.TimerAutoReset), DefaultValue(true)]
078 public bool AutoReset {
079 get {
080 return this.autoReset;
081 }
082
083 set {
084 if (DesignMode)
085 this.autoReset = value;
086 else if (this.autoReset != value) {
087 this.autoReset = value;
088 if( timer != null) {
089 UpdateTimer();
090 }
091 }
092 }
093 }
094
095 /// <devdoc>
096 /// <para>Gets or sets a value indicating whether the <see cref='System.Timers.Timer'/>
097 /// is able
098 /// to raise events at a defined interval.</para>
099 /// </devdoc>
100 //[....] - The default value by design is false, don't change it.
101 [Category("Behavior"), TimersDescription(SR.TimerEnabled), DefaultValue(false)]
102 public bool Enabled {
103 get {
104 return this.enabled;
105 }
106
107 set {
108 if (DesignMode) {
109 this.delayedEnable = value;
110 this.enabled = value;
111 }
112 else if (initializing)
113 this.delayedEnable = value;
114 else if (enabled != value) {
115 if (!value) {
116 if( timer != null) {
117 cookie = null;
118 timer.Dispose();
119 timer = null;
120 }
121 enabled = value;
122 }
123 else {
124 enabled = value;
125 if( timer == null) {
126 if (disposed) {
127 throw new ObjectDisposedException(GetType().Name);
128 }
129
130 int i = (int)Math.Ceiling(interval);
131 cookie = new Object();
132 timer = new System.Threading.Timer(callback, cookie, i, autoReset? i:Timeout.Infinite);
133 }
134 else {
135 UpdateTimer();
136 }
137 }
138
139 }
140 }
141 }
142
143
144 private void UpdateTimer() {
145 int i = (int)Math.Ceiling(interval);
146 timer.Change(i, autoReset? i :Timeout.Infinite );
147 }
148
149 /// <devdoc>
150 /// <para>Gets or
151 /// sets the interval on which
152 /// to raise events.</para>
153 /// </devdoc>
154 [Category("Behavior"), TimersDescription(SR.TimerInterval), DefaultValue(100d), RecommendedAsConfigurable(true)]
155 public double Interval {
156 get {
157 return this.interval;
158 }
159
160 set {
161 if (value <= 0)
162 throw new ArgumentException(SR.GetString(SR.TimerInvalidInterval, value, 0));
163
164 interval = value;
165 if (timer != null) {
166 UpdateTimer();
167 }
168 }
169 }
170
171
172 /// <devdoc>
173 /// <para>Occurs when the <see cref='System.Timers.Timer.Interval'/> has
174 /// elapsed.</para>
175 /// </devdoc>
176 [Category("Behavior"), TimersDescription(SR.TimerIntervalElapsed)]
177 public event ElapsedEventHandler Elapsed {
178 add {
179 onIntervalElapsed += value;
180 }
181 remove {
182 onIntervalElapsed -= value;
183 }
184 }
185
186 /// <devdoc>
187 /// <para>
188 /// Sets the enable property in design mode to true by default.
189 /// </para>
190 /// </devdoc>
191 /// <internalonly/>
192 public override ISite Site {
193 set {
194 base.Site = value;
195 if (this.DesignMode)
196 this.enabled= true;
197 }
198
199 get {
200 return base.Site;
201 }
202 }
203
204
205 /// <devdoc>
206 /// <para>Gets or sets the object used to marshal event-handler calls that are issued when
207 /// an interval has elapsed.</para>
208 /// </devdoc>
209 [
210 Browsable(false),
211 DefaultValue(null),
212 TimersDescription(SR.TimerSynchronizingObject)
213 ]
214 public ISynchronizeInvoke SynchronizingObject {
215 get {
216 if (this.synchronizingObject == null && DesignMode) {
217 IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost));
218 if (host != null) {
219 object baseComponent = host.RootComponent;
220 if (baseComponent != null && baseComponent is ISynchronizeInvoke)
221 this.synchronizingObject = (ISynchronizeInvoke)baseComponent;
222 }
223 }
224
225 return this.synchronizingObject;
226 }
227
228 set {
229 this.synchronizingObject = value;
230 }
231 }
232
233 /// <devdoc>
234 /// <para>
235 /// Notifies
236 /// the object that initialization is beginning and tells it to stand by.
237 /// </para>
238 /// </devdoc>
239 public void BeginInit() {
240 this.Close();
241 this.initializing = true;
242 }
243
244 /// <devdoc>
245 /// <para>Disposes of the resources (other than memory) used by
246 /// the <see cref='System.Timers.Timer'/>.</para>
247 /// </devdoc>
248 public void Close() {
249 initializing = false;
250 delayedEnable = false;
251 enabled = false;
252
253 if (timer != null ) {
254 timer.Dispose();
255 timer = null;
256 }
257 }
258
259 /// <internalonly/>
260 /// <devdoc>
261 /// </devdoc>
262 protected override void Dispose(bool disposing) {
263 Close();
264 this.disposed = true;
265 base.Dispose(disposing);
266 }
267
268 /// <devdoc>
269 /// <para>
270 /// Notifies the object that initialization is complete.
271 /// </para>
272 /// </devdoc>
273 public void EndInit() {
274 this.initializing = false;
275 this.Enabled = this.delayedEnable;
276 }
277
278 /// <devdoc>
279 /// <para>Starts the timing by setting <see cref='System.Timers.Timer.Enabled'/> to <see langword='true'/>.</para>
280 /// </devdoc>
281 public void Start() {
282 Enabled = true;
283 }
284
285 /// <devdoc>
286 /// <para>
287 /// Stops the timing by setting <see cref='System.Timers.Timer.Enabled'/> to <see langword='false'/>.
288 /// </para>
289 /// </devdoc>
290 public void Stop() {
291 Enabled = false;
292 }
293
294 private void MyTimerCallback(object state) {
295 // System.Threading.Timer will not cancel the work item queued before the timer is stopped.
296 // We don't want to handle the callback after a timer is stopped.
297 if( state != cookie) {
298 return;
299 }
300
301 if (!this.autoReset) {
302 enabled = false;
303 }
304
305 FILE_TIME filetime = new FILE_TIME();
306 GetSystemTimeAsFileTime(ref filetime);
307 ElapsedEventArgs elapsedEventArgs = new ElapsedEventArgs(filetime.ftTimeLow, filetime.ftTimeHigh);
308 try {
309 // To avoid ---- between remove handler and raising the event
310 ElapsedEventHandler intervalElapsed = this.onIntervalElapsed;
311 if (intervalElapsed != null) {
312 if (this.SynchronizingObject != null && this.SynchronizingObject.InvokeRequired)
313 this.SynchronizingObject.BeginInvoke(intervalElapsed, new object[]{this, elapsedEventArgs});
314 else
315 intervalElapsed(this, elapsedEventArgs);
316 }
317 }
318 catch {
319 }
320 }
321
322 [StructLayout(LayoutKind.Sequential)]
323 internal struct FILE_TIME {
324 internal int ftTimeLow;
325 internal int ftTimeHigh;
326 }
327
328 [DllImport(ExternDll.Kernel32), SuppressUnmanagedCodeSecurityAttribute()]
329 internal static extern void GetSystemTimeAsFileTime(ref FILE_TIME lpSystemTimeAsFileTime);
330 }
331 }
332
333
334 // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
在初始化的时候它的代码实现是这样的.
1 public Timer()
2 : base() {
3 interval = 100;
4 enabled = false;
5 autoReset = true;
6 initializing = false;
7 delayedEnable = false;
8 callback = new TimerCallback(this.MyTimerCallback);
9 }
而如果你是这样的话
01 public Timer(double interval)
02 : this() {
03 if (interval <= 0)
04 throw new ArgumentException(SR.GetString(SR.InvalidParameter, "interval", interval));
05
06 int i = (int)Math.Ceiling(interval);
07 if( i < 0) {
08 throw new ArgumentException(SR.GetString(SR.InvalidParameter, "interval", interval));
09 }
10
11 this.interval = interval;
12 }
你就需要再设置下AutoReset = True;
我们加载事件的Elapsed的代码实现是这样的.
01 /// <devdoc>
02 /// <para>Occurs when the <see cref='System.Timers.Timer.Interval'/> has
03 /// elapsed.</para>
04 /// </devdoc>
05 [Category("Behavior"), TimersDescription(SR.TimerIntervalElapsed)]
06 public event ElapsedEventHandler Elapsed {
07 add {
08 onIntervalElapsed += value;
09 }
10 remove {
11 onIntervalElapsed -= value;
12 }
13 }
对它的基本原理有一定了解后,我们开始写一个简单的实现程序。
01 using System;
02 using System.Collections.Generic;
03 using System.Linq;
04 using System.Text;
05 using System.Threading;
06 using Timer = System.Timers.Timer;
07 using System.Timers;
08
09 namespace TestMultipleThread
10 {
11
12 public class ThreadWork
13 {
14 private System.Timers.Timer _TestTimerEvent;
15
16 public void StartWork()
17 {
18 _TestTimerEvent = new Timer();
19 _TestTimerEvent.Elapsed += Sum;
20 _TestTimerEvent.Start();
21 }
22
23 public static object lockobject = new object();
24
25
26 private void Sum(object sender, ElapsedEventArgs e)
27 {
28 Console.WriteLine(string.Format("this is thread ID {0} execute", Thread.CurrentThread.ManagedThreadId));
29 for (int i = 0; i < 10000; i++)
30 {
31 Thread.Sleep(10);
32 }
33 }
34 }
35
36 class Program
37 {
38 public static void Main()
39 {
40 ThreadWork threadWork = new ThreadWork();
41 ThreadStart myThreadDelegate = new ThreadStart(threadWork.StartWork);
42 Thread myThread = new Thread(myThreadDelegate);
43 myThread.Start();
44
45 Thread.Sleep(1000000);
46 }
47 }
48 }
查看的运行结果是:
我们看下执行的线程数有多少
能说明的一个问题就是在timer每次执行时都会新起一个线程来执行。
.NET System.Timers.Timer的原理和使用(开发定时执行程序)的更多相关文章
- System.Timers.Timer
前言 System.Timers.Timer组件是基于服务器的计时器,它能够指定在应用程序中引发Elapsed事件周期性间隔,以处理相应事件. 使用示例: 运行结果展示: System.Timers. ...
- C# System.Timers.Timer的一些小问题?
比如设置间隔时间是 1000msSystem.Timers.Timer mytimer = new System.Timers.Timer(1000);问题若响应函数执行的时间超过了 1000 ms, ...
- [C#]System.Timers.Timer
摘要 在.Net中有几种定时器,最喜欢用的是System.Timers命名空间下的定时器,使用起来比较简单,作为定时任务,有Quartz.net,但有时候,一个非常简单的任务,不想引入这个定时任务框架 ...
- C# --System.Timers.Timer 定时方法
注意Start() 注意要等Interval 时间间隔 static void Main(string[] args) { System.Timers.Timer t = new System.Tim ...
- System.Windows.Forms.Timer与System.Timers.Timer的区别(zz)
.NET Framework里面提供了三种Timer: System.Windows.Forms.Timer System.Timers.Timer System.Threading.Timer VS ...
- 使用System.Timers.Timer类实现程序定时执行
使用System.Timers.Timer类实现程序定时执行 在C#里关于定时器类有3个:System.Windows.Forms.Timer类.System.Threading.Timer类和Sys ...
- C# 定时器-System.Timers.Timer
using Newtonsoft.Json; using Rafy; using Rafy.Domain; using System; using System.Collections.Generic ...
- .Net Windows Service(服务) 调试安装及System.Timers.Timer 使用
Windows Service(服务) 是运行在后台的进程 1.VS建立 Windows 服务(.NET Framework) 2.添加Timer 双击Service1.cs可以拖控件(System ...
- System.Windows.Forms.Timer、System.Timers.Timer、System.Threading.Timer的 区别和用法
System.Windows.Forms.Timer执行的时候,如果你在过程中间加一个sleep整个的界面就死掉了,但是另外两个没有这个情况,System.Timers.Timer.System.Th ...
随机推荐
- 修改placeholder颜色
#contact_info为textarea的ID #contact_info::-webkit-input-placeholder{ color:#999;}#contact_info:-moz-p ...
- [PR & ML 1] [Introduction] Informal Basic Concepts
最近还没更完OpenCV又开了新坑,谁教machine learning处在紧急又重要的地位呢.更新的内容总结自Pattern Recognition and Machine Learning by ...
- bzoj1002:[FJOI2007]轮状病毒
思路:一道很裸的生成树计数问题,然而要高精度,而且听说直接行列式求值会被卡精度,所以可以模拟行列式求值的过程得到递推公式:f[i]=3*f[i-1]-f[i-2]+2,证明详见vfk博客: http: ...
- Build Error 6041: Internal build error
Note: Following content is reprinted from the Original article Flexera : Build Error 6041. Only for ...
- STL容器与配接器
STL容器包括顺序容器.关联容器.无序关联容器 STL配接器包括容器配接器.函数配接器 顺序容器: vector 行为类似于数组,但可以根据要求 ...
- jquery.animate用法
<!DOCTYPE html><html><head><script src="http://libs.baidu.com/jquery/1.10. ...
- 3d旋转--transform-style: preserve-3d,translate3d(x,y,z),perspective()
transform-style: preserve-3d,translate3d(x,y,z),perspective() 让其倾斜的核心:加perspective(600px)让其动的核心:rans ...
- JavaScript的语法要点 2 - Scope Chain
前文所述,JavaScript是基于词法作用域(lexically scoped)的,所以标识符被固定在它们被定义的作用域而不是语法上或是其被调用时的作用域.即全局变量的作用域是整个程序,局部变量的作 ...
- php 开启缓冲,页面纯静态化
服务器默认不开启php缓冲区 两种方法开启 1.php.ini out_put_buffer = on 2.ob_start(); 页面纯静态化 file_put_contents()写文件 ob_s ...
- Python获取两个ip之间的所有ip
int_ip = lambda x: '.'.join([str(x/(256**i)%256) for i in range(3,-1,-1)]) ip_int = lambda x:sum([25 ...