.NET Framework v2.0 中新增了一个 System.Diagnostics.Stopwatch 对象,本文就是说用它来计算时间差,.NET 2.0 中是现成的,因此对 2.0 来说,这文章没什么意义,只要知道有这个对象就可以了,用法也相当简单,举例:
public
void
SomeMethod()
{
Stopwatch stopwatch = Stopwatch.StartNew();
// do something
// 仅仅简单举例, Stopwatch 还提供了其他更为详细的属性和方法。
Console.WriteLine( " Elapsed Seconds: {0} " , stopwatch.Elapsed.TotalSeconds);
}
{
Stopwatch stopwatch = Stopwatch.StartNew();
// do something
// 仅仅简单举例, Stopwatch 还提供了其他更为详细的属性和方法。
Console.WriteLine( " Elapsed Seconds: {0} " , stopwatch.Elapsed.TotalSeconds);
}
在 1.1 里没有提供,但只需把该对象完整的反编译代码 Copy 出来自建一个 Stopwatch 对象,再做一点小改动就 OK 了。 代码与举例:
using
System;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
namespace Zealot.Framework.Web.Utils
{
/// <summary>
/// v1.1 没有 Stopwatch,从 v2.0 复制出来
/// </summary>
public class Stopwatch
{
// Fields
private long elapsed;
public static readonly long Frequency;
public static readonly bool IsHighResolution;
private bool isRunning;
private long startTimeStamp;
private static readonly double tickFrequency;
private const long TicksPerMillisecond = 0x2710 ;
private const long TicksPerSecond = 0x989680 ;
// Methods
static Stopwatch()
{
if ( ! SafeNativeMethods.QueryPerformanceFrequency( out Frequency))
{
IsHighResolution = false ;
Frequency = 0x989680 ;
tickFrequency = 1 ;
}
else
{
IsHighResolution = true ;
tickFrequency = 10000000 ;
tickFrequency /= ( double )Frequency;
}
}
public Stopwatch()
{
this .Reset();
}
private long GetElapsedDateTimeTicks()
{
long rawElapsedTicks = this .GetRawElapsedTicks();
if (IsHighResolution)
{
double num2 = rawElapsedTicks;
num2 *= tickFrequency;
return ( long )num2;
}
return rawElapsedTicks;
}
private long GetRawElapsedTicks()
{
long elapsed = this .elapsed;
if ( this .isRunning)
{
long num3 = GetTimestamp() - this .startTimeStamp;
elapsed += num3;
}
return elapsed;
}
public static long GetTimestamp()
{
if (IsHighResolution)
{
long num = 0 ;
SafeNativeMethods.QueryPerformanceCounter( out num);
return num;
}
return DateTime.UtcNow.Ticks;
}
public void Reset()
{
this .elapsed = 0 ;
this .isRunning = false ;
this .startTimeStamp = 0 ;
}
public void Start()
{
if ( ! this .isRunning)
{
this .startTimeStamp = GetTimestamp();
this .isRunning = true ;
}
}
public static Stopwatch StartNew()
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
return stopwatch;
}
public void Stop()
{
if ( this .isRunning)
{
long num2 = GetTimestamp() - this .startTimeStamp;
this .elapsed += num2;
this .isRunning = false ;
}
}
// Properties
public TimeSpan Elapsed
{
get
{
return new TimeSpan( this .GetElapsedDateTimeTicks());
}
}
public long ElapsedMilliseconds
{
get
{
return ( this .GetElapsedDateTimeTicks() / (( long ) 0x2710 ));
}
}
public long ElapsedTicks
{
get
{
return this .GetRawElapsedTicks();
}
}
public bool IsRunning
{
get
{
return this .isRunning;
}
}
}
}
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
namespace Zealot.Framework.Web.Utils
{
/// <summary>
/// v1.1 没有 Stopwatch,从 v2.0 复制出来
/// </summary>
public class Stopwatch
{
// Fields
private long elapsed;
public static readonly long Frequency;
public static readonly bool IsHighResolution;
private bool isRunning;
private long startTimeStamp;
private static readonly double tickFrequency;
private const long TicksPerMillisecond = 0x2710 ;
private const long TicksPerSecond = 0x989680 ;
// Methods
static Stopwatch()
{
if ( ! SafeNativeMethods.QueryPerformanceFrequency( out Frequency))
{
IsHighResolution = false ;
Frequency = 0x989680 ;
tickFrequency = 1 ;
}
else
{
IsHighResolution = true ;
tickFrequency = 10000000 ;
tickFrequency /= ( double )Frequency;
}
}
public Stopwatch()
{
this .Reset();
}
private long GetElapsedDateTimeTicks()
{
long rawElapsedTicks = this .GetRawElapsedTicks();
if (IsHighResolution)
{
double num2 = rawElapsedTicks;
num2 *= tickFrequency;
return ( long )num2;
}
return rawElapsedTicks;
}
private long GetRawElapsedTicks()
{
long elapsed = this .elapsed;
if ( this .isRunning)
{
long num3 = GetTimestamp() - this .startTimeStamp;
elapsed += num3;
}
return elapsed;
}
public static long GetTimestamp()
{
if (IsHighResolution)
{
long num = 0 ;
SafeNativeMethods.QueryPerformanceCounter( out num);
return num;
}
return DateTime.UtcNow.Ticks;
}
public void Reset()
{
this .elapsed = 0 ;
this .isRunning = false ;
this .startTimeStamp = 0 ;
}
public void Start()
{
if ( ! this .isRunning)
{
this .startTimeStamp = GetTimestamp();
this .isRunning = true ;
}
}
public static Stopwatch StartNew()
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
return stopwatch;
}
public void Stop()
{
if ( this .isRunning)
{
long num2 = GetTimestamp() - this .startTimeStamp;
this .elapsed += num2;
this .isRunning = false ;
}
}
// Properties
public TimeSpan Elapsed
{
get
{
return new TimeSpan( this .GetElapsedDateTimeTicks());
}
}
public long ElapsedMilliseconds
{
get
{
return ( this .GetElapsedDateTimeTicks() / (( long ) 0x2710 ));
}
}
public long ElapsedTicks
{
get
{
return this .GetRawElapsedTicks();
}
}
public bool IsRunning
{
get
{
return this .isRunning;
}
}
}
}
编译时发现有 2 处错误,无法找到 SafeNativeMethods 对象,因为它是 internal 访问限制的。 而 在这个类里用到了 SafeNativeMethods 中的两个方法,QueryPerformanceFrequency 和 QueryPerformanceCounter,把他们也反编译出来,直接加入自建的 Stopwatch 类当中,或者在与 Stopwatch 相同的命名空间下同样自建一个 SafeNativeMethods 类就可以了。
using
System;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
namespace Zealot.Framework.Web.Utils
{
[SuppressUnmanagedCodeSecurity]
internal class SafeNativeMethods
{
[DllImport( " kernel32.dll " )]
internal static extern bool QueryPerformanceCounter( out long value);
[DllImport( " kernel32.dll " )]
internal static extern bool QueryPerformanceFrequency( out long value);
}
}
转自:http://www.zealotforce.net/reply-638.aspx
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
namespace Zealot.Framework.Web.Utils
{
[SuppressUnmanagedCodeSecurity]
internal class SafeNativeMethods
{
[DllImport( " kernel32.dll " )]
internal static extern bool QueryPerformanceCounter( out long value);
[DllImport( " kernel32.dll " )]
internal static extern bool QueryPerformanceFrequency( out long value);
}
}