41

I want to call thread sleep with less than 1 millisecond. I read that neither thread.Sleep nor Windows-OS support that.

What's the solution for that?

For all those who wonder why I need this: I'm doing a stress test, and want to know how many messages my module can handle per second. So my code is:

 // Set the relative part of Second hat will be allocated for each message 
 //For example: 5 messages - every message will get 200 miliseconds 
 var quantum = 1000 / numOfMessages;

 for (var i = 0; i < numOfMessages; i++)
 {
      _bus.Publish(new MyMessage());
      if (rate != 0) 
          Thread.Sleep(quantum);
 }

I'll be glad to get your opinion on that.

Eliahu Aaron
  • 4,103
  • 5
  • 27
  • 37
Erez
  • 6,405
  • 14
  • 70
  • 124
  • 8
    Why do you want to do that? The solution is probably to approach your problem in a more suitable way. ;-) – Achim Jun 06 '11 at 15:59
  • 3
    If it's not supported by the OS then no, you cannot. Why do you want to do this? – zellio Jun 06 '11 at 16:00
  • 1
    and what is purpose of this if I may ask? – evilone Jun 06 '11 at 16:00
  • 1
    You can't do this; Thread.Sleep will almost always yield execution of your thread, and you cannot control or predict when the OS decides to schedule it again. Sleeping precise amounts of time is impossible on a non-realtime OS. – Sven Jun 06 '11 at 16:02

6 Answers6

53

You can't do this. A single sleep call will typically block for far longer than a millisecond (it's OS and system dependent, but in my experience, Thread.Sleep(1) tends to block for somewhere between 12-15ms).

Windows, in general, is not designed as a real-time operating system. This type of control is typically impossible to achieve on normal (desktop/server) versions of Windows.

The closest you can get is typically to spin and eat CPU cycles until you've achieved the wait time you want (measured with a high performance counter). This, however, is pretty awful - you'll eat up an entire CPU, and even then, you'll likely get preempted by the OS at times and effectively "sleep" for longer than 1ms...

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • 12
    For others coming to this thread, I tested to verify with Mono C# under linux/ubuntu using Thread.Sleep(1), it sleeps the thread for precisely 1ms. – JaredBroad Sep 25 '14 at 04:59
  • 2
    Vista and newer support tickless scheduling. If the hardware supports this, the kernel can schedule below 1ms, but sleep is limited to 1ms. Remember, sleep is only guaranteed to sleep for at least that amount of time, but no guarantees when the thread will wake up. – Bengie Dec 07 '15 at 19:33
  • 2
    I hate this answer. It's technically correct with regards to sleeping, but as far as what the OP and most people want there is a brute-force but very effective solution by Sam below. The high upvotes and firm "You can't do this" on this answer dissuades people from scrolling down and finding their solution. – jalalipop May 24 '19 at 18:15
  • 1
    @jalalipop The entire last paragraph is describing the technique mentioned below - which, as I say, still doesn't necessarily work properly (as you can get preempted), though it does allow for more precision. That being said, SpinWait is a better approach than the one below if that's what you're doing - see https://learn.microsoft.com/en-us/dotnet/api/system.threading.thread.spinwait?view=netframework-4.8 – Reed Copsey May 29 '19 at 16:07
  • @ReedCopsey I don't think just spinning directly solves the issue either, it's the use of the stopwatch in Sam's answer that makes it spot on. – jalalipop May 30 '19 at 17:41
  • @jalalipop you need both, ideally. Spinning is better than a while loop, but you need the SW for timing. That being said, you can still be preempted, so it's not a real solution, just an approximation that eats cpu. – Reed Copsey May 31 '19 at 02:14
  • I recently solved that (kind of) by just spinning until `Stopwatch.ElapsedTicks` match the desired time. It works surprisingly well and I used it for simulating asynchronous data provider. 1ms worked slower than my typical network download, so I set my own `WaitAsync()` that allowed to specify times like 0.1ms. Now it behaves more like real dl, even with irregular speed ;) It's next to useless if you want precise delay, but when +/- 50% is fine, then this is perfect. – Harry Oct 07 '21 at 06:19
  • I recently found when having Thread.Sleep(1) in dotnet core 6 app runs on linux amd64, it actually sleeps exactly 1 second. Of course on Windows machines, it still sleeps between 2-15 ms. – Adamy Oct 18 '22 at 21:43
31

The code below will most definitely offer a more precise way of blocking, rather than calling Thread.Sleep(x); (although this method will block the thread, not put it to sleep). Below we are using the StopWatch class to measure how long we need to keep looping and block the calling thread.

using System.Diagnostics;

private static void NOP(double durationSeconds)
{
    var durationTicks = Math.Round(durationSeconds * Stopwatch.Frequency);
    var sw = Stopwatch.StartNew();

    while (sw.ElapsedTicks < durationTicks)
    {

    }
}

Example usage,

private static void Main()
{
    NOP(5); // Wait 5 seconds.

    Console.WriteLine("Hello World!");

    Console.ReadLine();
}
Sam
  • 7,252
  • 16
  • 46
  • 65
  • 10
    The question is explicitly asking for how to ***sleep*** for less than 1ms. This answer will ***block*** instead of sleep. Because the question is about a stress test it might be good enough in this instance so am up-voting it anyway. – nathanchere Apr 14 '14 at 06:27
  • Good point. Forgot to mention that in my post, just updated it now. – Sam Apr 14 '14 at 11:33
  • 1
    For coolness, you could also add var sw = Stopwatch.StartNew(); Less one line of code :) – TravisWhidden Feb 13 '16 at 20:48
  • Nice, I wasn't aware of that. – Sam Feb 13 '16 at 20:50
  • How long is a tick here, 100 nanoseconds ? Is this consistent on every machine ? – Saryk Jun 07 '17 at 13:36
  • 3
    @Saryk According to [this](https://stackoverflow.com/a/5793829/2246344) post, the duration of a tick is dependant on the OS/hardware. However, you can use the `Stopwatch`'s [`Frequency`](https://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.frequency(v=vs.110).aspx) property to determine the exact length of a tick on your machine. – Sam Jun 12 '17 at 11:36
  • This worked for me. Reading all the stuff about unavoidable latency. Im my case I needed to count to a number in a certain amount of time (500 ms) for a dmx lighting program. Thread.Sleep did indeed add 12-15ms per trip. so trip took 750ms.. When using this, the loop executes in 510ms! Just divide by 1000 to get ms – Tim Davis Oct 24 '18 at 18:43
  • The old days time simulator in DOS will tell you that this won't work if someone press the "TURBO" button @Sam is right. This definitely wont work AND where is less than 1ms? – Leandro Bardelli Mar 11 '23 at 16:31
13

Why?
Usually there are a very limited number of CPUs and cores on one machine - you get just a small number if independent execution units.

From the other hands there are a number of processes and many more threads. Each thread requires some processor time, that is assigned internally by Windows core processes. Usually Windows blocks all threads and gives a certain amount of CPU core time to particular threads, then it switches the context to other threads.

When you call Thread.Sleep no matter how small you kill the whole time span Windows gave to the thread, as there is no reason to simply wait for it and the context is switched straight away. It can take a few ms when Windows gives your thread some CPU next time.

What to use?
Alternatively, you can spin your CPU, spinning is not a terrible thing to do and can be very useful. It is for example used in System.Collections.Concurrent namespace a lot with non-blocking collections, e.g.:

SpinWait sw = new SpinWait();
sw.SpinOnce();
oleksii
  • 35,458
  • 16
  • 93
  • 163
8

Most of the legitimate reasons for using Thread.Sleep(1) or Thread.Sleep(0) involve fairly advanced thread synchronization techniques. Like Reed said, you will not get the desired resolution using conventional techniques. I do not know for sure what it is you are trying to accomplish, but I think I can assume that you want to cause an action to occur at 1 millisecond intervals. If that is the case then take a look at multimedia timers. They can provide resolution down to 1ms. Unfortunately, there is no API built into the .NET Framework (that I am aware of) that taps into this Windows feature. But you can use the interop layer to call directly into the Win32 APIs. There are even examples of doing this in C# out there.

Community
  • 1
  • 1
Brian Gideon
  • 47,849
  • 13
  • 107
  • 150
6

In the good old days, you would use the "QueryPerformanceTimer" API of Win32, when sub milisecond resolution was needed.

There seems to be more info on the subject over on Code-Project: http://www.codeproject.com/KB/cs/highperformancetimercshar.aspx

This won't allow you to "Sleep()" with the same resolution as pointed out by Reed Copsey.

Edit: As pointed out by Reed Copsey and Brian Gideon the QueryPerfomanceTimer has been replaced by Stopwatch in .NET

S.C. Madsen
  • 5,100
  • 5
  • 32
  • 50
  • 2
    This doesn't block - it just gives you a way to measure. The `Stopwatch` class effectively does this in C# (by using `QueryPerformanceCounter` internally). – Reed Copsey Jun 06 '11 at 16:05
  • No, but it provides a reference of time with higher resolution. I have no idea what Erez is up to, but i reckon he could approach his problem differently, using the performance-timer (Edit: StopWatch, did'nt know that one, thanks) instead... – S.C. Madsen Jun 06 '11 at 16:09
  • 1
    +1: Yes, this is a reasonable approach. Except I would mention `Stopwatch` instead of `QueryPerformanceCounter`. – Brian Gideon Jun 07 '11 at 12:57
  • Thanks Brian, Yes I totally agree that Stopwatch should be used instead. I'll put that in my reponse. – S.C. Madsen Jun 15 '11 at 10:29
1

I was looking for the same thing as the OP, and managed to find an answer that works for me. I'm surprised that none of the other answers mentioned this.

When you call Thread.Sleep(), you can use one of two overloads: An int with the number of milliseconds, or a TimeSpan.

A TimeSpan's Constructor, in turn, has a number of overloads. One of them is a single long denoting the number of ticks the TimeSpan represents. One tick is a lot less than 1ms. In fact, another part of TimeSpan's docs gave an example of 10000 ticks happening in 1ms.

Therefore, I think the closest answer to the question is that if you want Thread.Sleep for less than 1ms, you would create a TimeSpan with less than 1ms worth of ticks, then pass that to Thread.Sleep().

XJDHDR
  • 494
  • 5
  • 15
  • I found when trying to do this, any time less than 1ms isn't actually waited. Examples: `Thread.Sleep(Timespan.FromTicks(9999));` = no delay `Thread.Sleep(Timespan.FromTicks(10000));` = delay over 1 ms – JasonC Aug 08 '23 at 22:24