计时器在很多应用场景中广泛应用,System.Threading命名空间下,有个Timer类可以完成计时器的操作。
下面来讨论下Timer类的使用及多个CPU内核同时运行线程时如何共享高速缓存(cache)的。
主要内容:
1. 计时器的使用
1.1 计时器的创建及改变设置
计时器创建的API都类似,有以下5种:
1
2
3
4
5
|
public Timer(TimerCallback callback);
public Timer(TimerCallback callback, object state, int dueTime, int period);
public Timer(TimerCallback callback, object state, long dueTime, long period);
public Timer(TimerCallback callback, object state, TimeSpan dueTime, TimeSpan period);
public Timer(TimerCallback callback, object state, uint dueTime, uint period);
|
其中各个参数的含义如下:
-
callback:定时执行的操作
-
state:传递给callback的参数
-
dueTime:首次调用callback时,需要等待多少毫秒
-
period:每隔多少毫秒执行一次callback
下面例子演示如何创建一个计时器,并且在运行10秒后如何改变计时器的dueTime和period
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
using System;
using System.Threading;
public class CLRviaCSharp_20
{
static void Main( string [] args)
{
// 定义一个定时器,每2秒执行一次
Timer t = new Timer(PrintTime, "Timer Test" , 0, 2000);
// 主线程等待10秒(让计时器先执行6次)
Thread.Sleep(10000);
// 改变计时器的设置,停3秒后,每2秒执行一次
t.Change(3000, 1000);
Console.ReadKey( true );
}
private static void PrintTime( object state)
{
Thread.Sleep(3000);
Console.WriteLine( "{0}: Now is {1}" , state, DateTime.Now);
}
}
|
运行上面的例子,我们发现有以下现象:
- 刚开始每隔2秒打印一次当前时间
- 10秒后,每隔1秒打印一次当前时间
- callback(即PrintTime函数)中虽然有Sleep(3000);但计时器的下一次callback并没有等待本次callback完成就开始运行了。
对于上述的第三点,是由于Timer在每个period到期时,如果上个callback没完成,会在线程池中再启动一个线程来完成本次的callback。
1.2 耗时操作(操作消耗的时间 > 计时器的时间间隔)
但是,对于某些应用场景,可能需要callback一个一个顺序执行。
如果callback的耗时较长,希望下次callback能在本次callback完成后,再过period后执行。这时,就需要我们使用Timer的Change方法实现。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
using System;
using System.Threading;
public class CLRviaCSharp_20
{
static Timer t;
static void Main( string [] args)
{
// 定义一个计时器,
// period参数设置为Timeout.Infinite的意思是计时器执行一次就结束
t = new Timer(PrintTime, "Timer Test" , 0, Timeout.Infinite);
Console.ReadKey( true );
}
private static void PrintTime( object state)
{
Thread.Sleep(3000);
Console.WriteLine( "{0}: Now is {1}" , state, DateTime.Now);
// 因为计时器执行一次就结束,所以在callback(即PrintTime)执行完后再启动一个计时器
// 此计时器仍然设置period参数设置为Timeout.Infinite
// 并且设置dueTime参数为2000毫秒,从而保证下次callback在本次callback完成2秒后执行
// 这样不管每个callback耗用多少时间,两个callback之间的间隔时间始终是2秒
t = new Timer(PrintTime, "Timer Test" , 2000, Timeout.Infinite);
|
请发表评论