I’m using Thread.SpinWait on a special thread to create a near-exact 2ms delay with minimal chance of a context switch, needed for precise hardware communication timing. But using a profiler, I’ve noticed that if the main thread does something that takes over 100ms, the Thread.SpinWait will as well. Am I misunderstanding what Thread.SpinWait does? Is it not running on the thread it is called from?
-
You can't prevent the kernel scheduler from pre-emptively knocking off your thread even if you are busy-waiting, if another thread demands the processor. You only get a small timeslice to do everything you need. `SpinWait` is not accurate in that way, and very few kernels have accurate enough timing mechanisms for 2ms, Windows is no exception. – Charlieface Jul 20 '22 at 20:33
-
Put it another way: if you need precise timing you need a realtime kernel, which Windows and Linux (and pretty much any x86 kernel) is not. You need a realtime chip – Charlieface Jul 21 '22 at 09:42
1 Answers
First of all read this a couple of times: https://learn.microsoft.com/en-us/dotnet/standard/threading/spinwait
"will itself initiate context switches if it spins long enough (roughly the length of time required for a kernel transition)." compared with the " because spinning blocks forward progress on all threads" and hence depending on available cores this can behave differently but at least requires that you want to be blocking all threads and like you have observed, it cannot block before it can lock so it will have to wait for anything it cannot freeze in what it is doing and seem like taking that time extra.
If you need to do something every 2. ms, consider making a timer tick with that frequency together with a ManualResetEvent you can make your main thread execute with this frequency, but you cannot make it execute before it can get cpu time so when you main thread is doing something else, 'you' will have to wait.
Still in my oppinion it is a mistake to want to control the context switching from .net it is too high level and like @Charlieface outline, you will have to get special hardware to even be able!
So in the "do the right things right" spirit, take perhaps a step back and consider what it is that you are trying to do and if that really requires you to control hardware cpu context switching.
In .net a good size for a non generically implemented wait needs to be at least 16 ms as the minimal size for Task.Delay is just under that period and then you would await that delay.
I could easily be wrong, but it looks like you're trying to do the wrong thing right by implementing what solution you need in a problematic way, after all would we ever really want to be blocking anyway, in a high performance system?

- 835
- 5
- 18