简单地使用 beginDate - endDate 不精确,总是某个值的倍数,比如 0.015625 秒的倍数,值比较小时,干脆就是个0 (0 倍)。
.NET Framework v2.0 中新增了一个 System.Diagnostics.Stopwatch 对象,本文就是说用它来计算时间差,.NET 2.0 中是现成的,因此对 2.0 来说,这文章没什么意义,只要知道有这个对象就可以了,用法也相当简单,举例:
在 1.1 里没有提供,但只需把该对象完整的反编译代码 Copy 出来自建一个 Stopwatch 对象,再做一点小改动就 OK 了。 代码与举例:
编译时发现有 2 处错误,无法找到 SafeNativeMethods 对象,因为它是 internal 访问限制的。 而 在这个类里用到了 SafeNativeMethods 中的两个方法,QueryPerformanceFrequency 和 QueryPerformanceCounter,把他们也反编译出来,直接加入自建的 Stopwatch 类当中,或者在与 Stopwatch 相同的命名空间下同样自建一个 SafeNativeMethods 类就可以了。
.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);
}
}