在我的电脑上,秒表的返回值太低。例如,当我指定Thread.Sleep(1000)
时,为200毫秒。该程序应该等待1秒钟。我还用ManualResetEvent.WaitOne(1000)
进行了测试,得到了相同的结果。框架2.0和3.0都给出了这种奇怪的行为。我使用.NET Framework 3.5 SP1运行Windows XP SP3。.NET System.Diagnostics.Stopwatch问题(返回值太低)
这里是我的测试结果(下面的代码):
1000 ms for DateTime.Now.Ticks
0201 ms for Stopwatch.ElapsedTicks
0142 ms for Stopwatch.ElapsedMilliseconds
0139 ms for Stopwatch.ElapsedTicks after Reset
0264 ms for Stopwatch.ElapsedTicks setting ThreadAffinity
0151 ms for Stopwatch.ElapsedTicks setting ProcessorAffinity (and more)
0371 ms for Stopwatch.ElapsedTicks with Syncronized object
Done!
// Program.cs的文件
class Program
{
static void Main(string[] args)
{
StopWatchTest.Go();
Console.WriteLine("Done!");
Console.ReadLine();
}
}
// StopWatchTest.cs类
internal static class StopWatchTest
{
public const int SleepTime = 1000;
public static void Go()
{
#region Test #0 with DateTime.Now.Ticks
long startTick = DateTime.Now.Ticks;
Thread.Sleep(SleepTime);
long stopTick = DateTime.Now.Ticks;
long elapsedDt = (stopTick - startTick) * 100;
Display((int)(elapsedDt/1000/1000), "DateTime.Now.Ticks");
#endregion Test #0 with DateTime.Now.Ticks
Stopwatch watch = Stopwatch.StartNew();
long frequency = Stopwatch.Frequency;
double nanosecPerTick = (1000.0 * 1000.0 * 1000.0)/frequency;
#region Test #1 with Stopwatch.ElapsedTicks
startTick = watch.ElapsedTicks;
Thread.Sleep(SleepTime);
stopTick = watch.ElapsedTicks;
double elapsedSw = (stopTick - startTick) * nanosecPerTick;
Display((int)(elapsedSw/1000/1000), "Stopwatch.ElapsedTicks");
#endregion Test #1 with Stopwatch.ElapsedTicks
#region Test #2 with Stopwatch.ElapsedMilliseconds
startTick = watch.ElapsedMilliseconds;
Thread.Sleep(SleepTime);
stopTick = watch.ElapsedMilliseconds;
Display((int)(stopTick - startTick), "Stopwatch.ElapsedMilliseconds");
#endregion Test #2 with Stopwatch.ElapsedMilliseconds
#region Test #3 with Stopwatch.ElapsedTicks after Reset
watch.Stop();
watch.Reset();
watch.Start();
startTick = watch.ElapsedTicks;
Thread.Sleep(SleepTime);
stopTick = watch.ElapsedTicks;
elapsedSw = (stopTick - startTick) * nanosecPerTick;
Display((int)(elapsedSw/1000/1000), "Stopwatch.ElapsedTicks after Reset");
#endregion Test #3 with Stopwatch.ElapsedTicks after Reset
#region Test #4 with Stopwatch.ElapsedTicks and ThreadAffinity
Thread.BeginThreadAffinity();
startTick = watch.ElapsedTicks;
Thread.Sleep(SleepTime);
stopTick = watch.ElapsedTicks;
elapsedSw = (stopTick - startTick) * nanosecPerTick;
Display((int)(elapsedSw/1000/1000), "Stopwatch.ElapsedTicks setting ThreadAffinity");
Thread.EndThreadAffinity();
#endregion Test #4 with Stopwatch.ElapsedTicks and ThreadAffinity
#region Test #5 with Stopwatch.ElapsedTicks and ProcessorAffinity (and more)
const int affinity = 0x0001;
Process proc = Process.GetCurrentProcess();
proc.ProcessorAffinity = new IntPtr(affinity);
proc.PriorityClass = ProcessPriorityClass.High;
ProcessThreadCollection ptc = proc.Threads;
foreach (ProcessThread pt in ptc)
{
pt.IdealProcessor = 0;
pt.ProcessorAffinity = new IntPtr(affinity);
}
Thread.CurrentThread.Priority = ThreadPriority.Highest;
startTick = watch.ElapsedTicks;
Thread.Sleep(SleepTime);
stopTick = watch.ElapsedTicks;
elapsedSw = (stopTick - startTick) * nanosecPerTick;
Display((int)(elapsedSw/1000/1000), "Stopwatch.ElapsedTicks setting ProcessorAffinity (and more)");
#endregion Test #5 with ProcessorAffinity and more
#region Test #6 with Syncronized object
elapsedSw = new SyncTimer().Go();
Display((int)(elapsedSw/1000/1000), "Stopwatch.ElapsedTicks with Syncronized object");
#endregion Test #6 with Syncronized object
}
private static void Display(int milliseconds, string testName)
{
Console.WriteLine("{0:0000} ms for {1}", milliseconds, testName);
}
}
[Synchronization]
internal class SyncTimer : ContextBoundObject
{
[MethodImpl(MethodImplOptions.Synchronized)]
public double Go()
{
Stopwatch.StartNew();
long frequency = Stopwatch.Frequency;
double nanosecPerTick = (1000.0 * 1000.0 * 1000.0)/frequency;
long startTick = Stopwatch.GetTimestamp();
Thread.Sleep(StopWatchTest.SleepTime);
long stopTick = Stopwatch.GetTimestamp();
return (stopTick - startTick) * nanosecPerTick;
}
}
@ user633578,您的代码存在错误。您应该为每个测试使用一个秒表实例。 – acoolaum 2011-02-25 05:15:08
您必须将机器带到BIOS医生处。 – 2011-02-25 06:21:33
我没有看到任何有关重新使用相同的秒表实例的限制。顺便说一下,第一次测试不会产生有效的值。 – Ducharme 2011-02-25 07:01:57