刚才无聊,又看了看我记录的代码,无意中又看到了那个Stopwatch的代码。
现在大家都知道可以使用系统的Stopwatch计算时间。不过我们的鸡蛋同志,居然想自己实现Stopwatch。
这篇不属于wojilu的一个正式的原理解析,拿出来给大家讨论一下。
代码位置:wojilu\_wojilu\Stopwatch.cs
1 /*
2 * Copyright 2010 www.wojilu.com
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 using System;
18 using System.ComponentModel;
19 using System.Runtime.InteropServices;
20
21 namespace wojilu {
22
23 /// <summary>
24 /// 秒表,用于测试程序耗时
25 /// </summary>
26 public class Stopwatch {
27
28 private Boolean _IsStop;
29 private long frequency;
30 private decimal multiplier = 1000000000M;
31 private long start;
32 private long stop;
33
34 [DllImport( "KERNEL32" )]
35 private static extern Boolean QueryPerformanceCounter( out long lpPerformanceCount );
36
37 [DllImport( "Kernel32.dll" )]
38 private static extern Boolean QueryPerformanceFrequency( out long lpFrequency );
39
40 public Stopwatch() {
41 if (!QueryPerformanceFrequency( out this.frequency )) {
42 throw new Win32Exception();
43 }
44 }
45
46 /// <summary>
47 /// 开始启动
48 /// </summary>
49 public void Start() {
50 this._IsStop = false;
51 QueryPerformanceCounter( out this.start );
52 }
53
54 /// <summary>
55 /// 停止
56 /// </summary>
57 public void Stop() {
58 if (!this._IsStop) {
59 QueryPerformanceCounter( out this.stop );
60 this._IsStop = true;
61 }
62 }
63
64 /// <summary>
65 /// 总共耗时(毫秒)
66 /// </summary>
67 public double ElapsedMilliseconds {
68 get {
69 double result = this.getDuration() / 1000000.0;
70 if (result < 0) result = 0;
71 return result;
72 }
73 }
74
75 /// <summary>
76 /// 总共耗时(秒)
77 /// </summary>
78 public double ElapsedSeconds {
79 get {
80 double result = this.ElapsedMilliseconds / 1000.0;
81 if (result < 0) result = 0;
82 return result;
83 }
84 }
85
86 private double getDuration() {
87 return (((this.stop - this.start) * ((double)this.multiplier)) / ((double)this.frequency));
88 }
89
90 }
91 }
2 * Copyright 2010 www.wojilu.com
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 using System;
18 using System.ComponentModel;
19 using System.Runtime.InteropServices;
20
21 namespace wojilu {
22
23 /// <summary>
24 /// 秒表,用于测试程序耗时
25 /// </summary>
26 public class Stopwatch {
27
28 private Boolean _IsStop;
29 private long frequency;
30 private decimal multiplier = 1000000000M;
31 private long start;
32 private long stop;
33
34 [DllImport( "KERNEL32" )]
35 private static extern Boolean QueryPerformanceCounter( out long lpPerformanceCount );
36
37 [DllImport( "Kernel32.dll" )]
38 private static extern Boolean QueryPerformanceFrequency( out long lpFrequency );
39
40 public Stopwatch() {
41 if (!QueryPerformanceFrequency( out this.frequency )) {
42 throw new Win32Exception();
43 }
44 }
45
46 /// <summary>
47 /// 开始启动
48 /// </summary>
49 public void Start() {
50 this._IsStop = false;
51 QueryPerformanceCounter( out this.start );
52 }
53
54 /// <summary>
55 /// 停止
56 /// </summary>
57 public void Stop() {
58 if (!this._IsStop) {
59 QueryPerformanceCounter( out this.stop );
60 this._IsStop = true;
61 }
62 }
63
64 /// <summary>
65 /// 总共耗时(毫秒)
66 /// </summary>
67 public double ElapsedMilliseconds {
68 get {
69 double result = this.getDuration() / 1000000.0;
70 if (result < 0) result = 0;
71 return result;
72 }
73 }
74
75 /// <summary>
76 /// 总共耗时(秒)
77 /// </summary>
78 public double ElapsedSeconds {
79 get {
80 double result = this.ElapsedMilliseconds / 1000.0;
81 if (result < 0) result = 0;
82 return result;
83 }
84 }
85
86 private double getDuration() {
87 return (((this.stop - this.start) * ((double)this.multiplier)) / ((double)this.frequency));
88 }
89
90 }
91 }
Google大神给了我们这段代码的一些参考:
精确的时间计时,有时候是非常必要的。比如播放多媒体时视频与音频的时间同步,还有在测试代码的性能时,也需要使用到非常精确的时间计时。还有测试硬件的性能时,也需要精确的时间计时。这时就需要使用QueryPerformanceCounter来查询定时器的计数值,如果硬件里有定时器,它就会启动这个定时器,并且不断获取定时器的值,这样的定时器精度,就跟硬件时钟的晶振一样精确的。
函数QueryPerformanceCounter和QueryPerformanceFrequency声明如下:
WINBASEAPI
BOOL
WINAPI
QueryPerformanceCounter(
__out LARGE_INTEGER *lpPerformanceCount
);
WINBASEAPI
BOOL
WINAPI
QueryPerformanceFrequency(
__out LARGE_INTEGER *lpFrequency
);
BOOL
WINAPI
QueryPerformanceCounter(
__out LARGE_INTEGER *lpPerformanceCount
);
WINBASEAPI
BOOL
WINAPI
QueryPerformanceFrequency(
__out LARGE_INTEGER *lpFrequency
);
这个例子,大概能学到的东西,可能就是如何使用系统API在C#里面了。。。。呵呵
小品文,编辑大神,就让他留在首页吧。。。。鸡蛋同志写这段代码估计花了1个小时了。。。。。
我记录网址 http://www.wojilu.com/
欢迎大家加入我记录开发团队