Willy,
I'm sorry, but this is not correct, Thread.Sleep uses OS Kernel Waitable
timer objects who have a resolution of 1 msec.
Not on my system (XP/Pro/sp1) (the resolution, that is - I don't claim to
know how it's actually implemented).
If this were true , following
timeBeginPeriod(10000);
Thread.Sleep(1);
would sleep 10 sec.
I haven't tried it for anything above 50 mSecs, or so, so you could be
right. Isn't there an upper limit on what timeBeginPeriod supports anyway?
I wonder how you measured the sleep time on your system (sepecially those
below 10 msec).
QueryPerformanceCounter, but I won't keep you guessing at what I'm doing
You'll find my test code (that happened to still have lying around) below.
Try running the test as it is first, then comment out the call to
timeBeginPeriod and run it again.
Here are my results. Req is the argument to Sleep, Avg, Max, and Min are the
measured results.
With call to timeBeginPeriod:
Req:0 Avg:0.004 Max:0.256 Min:0
Req:1 Avg:1.96 Max:2.551 Min:1.613
Req:2 Avg:3.005 Max:11.561 Min:2.11
Req:3 Avg:3.904 Max:4.074 Min:3.743
Req:4 Avg:4.88 Max:4.917 Min:4.787
Req:5 Avg:5.857 Max:5.869 Min:5.768
Req:6 Avg:6.833 Max:6.933 Min:6.735
Req:7 Avg:7.81 Max:7.881 Min:7.711
Req:8 Avg:8.786 Max:8.823 Min:8.692
Req:9 Avg:9.763 Max:9.971 Min:9.565
Req:10 Avg:10.739 Max:10.749 Min:10.642
Req:11 Avg:11.716 Max:11.754 Min:11.617
Req:12 Avg:12.692 Max:12.708 Min:12.585
Req:13 Avg:13.669 Max:13.768 Min:13.569
Req:14 Avg:14.645 Max:14.657 Min:14.551
Req:15 Avg:15.622 Max:15.635 Min:15.533
Req:16 Avg:16.598 Max:16.68 Min:16.515
Req:17 Avg:17.575 Max:17.615 Min:17.483
Req:18 Avg:18.551 Max:18.57 Min:18.459
Req:19 Avg:19.528 Max:19.538 Min:19.426
Press <CR>
Without call to timeBeginPeriod:
Req:0 Avg:0.004 Max:0.258 Min:0
Req:1 Avg:15.541 Max:16.899 Min:7.66
Req:2 Avg:15.621 Max:15.788 Min:15.456
Req:3 Avg:15.622 Max:15.785 Min:15.464
Req:4 Avg:15.622 Max:15.811 Min:15.433
Req:5 Avg:15.622 Max:15.99 Min:15.264
Req:6 Avg:15.622 Max:15.719 Min:15.525
Req:7 Avg:15.622 Max:15.722 Min:15.523
Req:8 Avg:15.622 Max:15.956 Min:15.294
Req:9 Avg:15.622 Max:15.721 Min:15.526
Req:10 Avg:15.622 Max:15.721 Min:15.533
Req:11 Avg:15.622 Max:15.954 Min:15.304
Req:12 Avg:15.623 Max:15.724 Min:15.537
Req:13 Avg:15.621 Max:16.023 Min:15.291
Req:14 Avg:15.622 Max:15.93 Min:15.33
Req:15 Avg:15.622 Max:15.874 Min:15.373
Req:16 Avg:31.246 Max:31.512 Min:30.915
Req:17 Avg:31.246 Max:31.324 Min:31.128
Req:18 Avg:31.246 Max:31.581 Min:30.923
Req:19 Avg:31.246 Max:31.341 Min:31.16
Press <CR>
If I'm doing something wrong here, I'll be very interested to learn what it
is.
My system is a Dell 8300 P4@3GHz, in case that matters. Hyperthreading is
not enabled.
Oh, and I'm running this from within VS.NET1.1.
- Per
Waiter.cs:
-------------------------------------------------
using System;
using System.Runtime.InteropServices;
using System.Threading;
namespace WaitTest
{
/// <summary>
/// Summary description for Waiter.
/// </summary>
public class Waiter
{
internal const String WINMM = "winmm.dll";
internal const String KERNEL32 = "kernel32.dll";
[DllImport(WINMM)]
internal static extern uint timeBeginPeriod(
uint period);
[DllImport(WINMM)]
internal static extern uint timeEndPeriod(
uint period);
[DllImport(KERNEL32)]
internal static extern bool QueryPerformanceCounter(
out long PerformanceCount);
[DllImport(KERNEL32)]
internal static extern bool QueryPerformanceFrequency(
out long Frequency);
internal static long Freq;
static Waiter()
{
timeBeginPeriod(1);
QueryPerformanceFrequency(out Freq);
}
~Waiter()
{
timeEndPeriod(1);
}
static public long GetTimestamp()
{
long result;
QueryPerformanceCounter(out result);
return result;
}
static public long DeltaMilliseconds(long earlyTimestamp, long
lateTimestamp)
{
return (((lateTimestamp - earlyTimestamp) * 1000) / Freq);
}
static public long DeltaMicroseconds(long earlyTimestamp, long
lateTimestamp)
{
return (((lateTimestamp - earlyTimestamp) * 1000000) / Freq);
}
static public void Wait(int delay)
{
long Elapsed = 0;
long Before = GetTimestamp();
while (delay > Elapsed)
{
System.Threading.Thread.Sleep(delay);
Elapsed = DeltaMilliseconds(Before, GetTimestamp());
}
}
}
}
-------------------------------------------------
Class1.cs:
-------------------------------------------------
using System;
namespace WaitTest
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
int MaxDelay = 20;
int MaxLoopCount = 100;
for (int delay = 0; delay < MaxDelay; delay++)
{
long Total = 0;
long Max = 0;
long Min = 0;
for (int loopCount = 0; loopCount < MaxLoopCount; loopCount++)
{
long start = Waiter.GetTimestamp();
Waiter.Wait(delay);
long end = Waiter.GetTimestamp();
long actualDelay = Waiter.DeltaMicroseconds(start, end);
if (loopCount == 0)
{
Max = actualDelay;
Min = actualDelay;
}
else
{
if (actualDelay > Max)
Max = actualDelay;
if (actualDelay < Min)
Min = actualDelay;
}
Total += actualDelay;
}
Console.WriteLine("Req:{0} Avg:{1} Max:{2} Min:{3}",
delay, Total / MaxLoopCount / 1000.0, Max / 1000.0, Min / 1000.0);
}
Console.WriteLine("Press <CR>");
Console.ReadLine();
}
}
}
-------------------------------------------------