I was curious as to how Thread.Sleep was implemented. I had a look with Reflector for the implementation of Thread.Sleep. It calls the following function:
[MethodImpl(MethodImplOptions.InternalCall), SecurityCritical]
private static extern void SleepInternal(int millisecondsTimeout);
Does anyone know where that is defined? I am aware of other alternatives, such as Task.Delay. But was curious as to the actual implementation details.
Joe Duffy's book Concurrent Programming provides all of the details you need. But to summarize:
Thread.Sleep behaves similar to the Win API function SleepEx.
A duration parameter = 0 will cause the current thread to yield to another with equal or higher priority.
A duration parameter > 0 will cause a context switch and the current thread will remain in a Waiting state for until the specified amount of time has elapsed (approximately).
The thread will remain in an alertable state which means it is allowed to process APC methods via QueueUserAPC and will respond to Thread.Interrupt calls.
I recommend poking through the SSCLI code for a more complete understanding of how it is implemented.
Regarding your question about not being able to reuse the thread for other work...I am a bit confused. Thread.Sleep is a voluntary suspension so you (the programmer) told the thread not to do any more work. And like I mentioned above the thread is said to be alertable so you could actually interrupt it or even force it to do work via APC methods.
Refer to this question for more information about getting .NET threads to run APCs while Thread.Sleep is still pending.
Thread.Sleep() when called by a system thread (a real thread, not a user-thread) is a call that hooks into the OS kernel scheduling internals, similar to process sleep. It puts the execution context (that is visible at the kernel process level) into a "sleep" wait state so it consumes no CPU until it wakes up. It isn't a busy wait.
If you want it to be awake and/or doing other things, use some other mechanism besides Thread.Sleep().
Use await Task.Delay() if you want the thread to be reused
Related
I happened to lay my eyes on an intellisense tool tip regarding the parameter passed to System.Threading.Thread.Sleep(int millisecondsTimeout), saying something like "(…) Specify System.Threading.Timeout.Infinite to block the thread indefinitely". And I am intrigued.
I can understand why one might include short inactive delays within a possibly endless loop, thus yielding processing power to other executing threads when no immediate action in the sleeping thread is required, although I typically prefer implementing such delays with EventWaitHandlers so that I can avoid waiting a full sleeping delay if I signal the thread to gracefully end its execution from a different thread.
But I cannot see when I might need to suspend a thread indefinitely, and in a way that, as far as I can tell, can only be interrupted through a rather ungraceful Thread.Abort()/ThreadAbortException pair.
So what would be a working scenario where I might want to suspend a thread indefinitely?
It is a pretty long story and I have to wave my hands a bit to make it understandable. Most programmers think that Thread.Sleep() puts the thread to sleep and prevents it from executing any code. This is not accurate. Thread.Sleep(Infinite) is equivalent to Application.Run(). No kidding.
This doesn't happen very often in real life, it is mostly relevant in custom hosting scenarios. Getting code to run on a specific thread is in general an important feature to deal with code that is not thread-safe and the major reason why Application.Run() exists. But Windows exposes another way to do at a much lower level, the underlying api for this is QueueUserAPC(). The .NET analogue of this function is BeginInvoke().
This requires the thread to co-operate, just like it does when it calls Application.Run(). The thread must be in an "alertable wait state", executing a blocking function that can be interrupted. The CLR does not execute the sleep by itself, it passes the job to the CLR host. Most hosts will simply execute SleepEx(), passing TRUE for the bAlertable argument. The thread is now in a state to execute any requests posted by QueueUserAPC(). Just like it will be when it is actively executing inside the Application.Run() dispatcher loop.
The kernel feature is not otherwise exposed at all in the framework. It is the kind of code that is very hard to get right, re-entrancy bugs are pretty nasty. As most programmers that were bitten by Application.DoEvents() or a poorly placed MessageBox.Show() can attest. It is however a valid scenario in a custom hosting scenario. Where the host can get C# code to run on a specific thread, using this mechanism. So it is possible to pass Infinite because the designers did not want to intentionally disable this scenario. If this is made possible at all by the host author then they'd let you know about it. I don't know of a practical example.
More practically, you do use this feature every day. It is the way that System.Threading.Timer and System.Timers.Timer are implemented. Done by a thread inside the CLR which is started as soon as you use any timer, it uses SleepEx(INFINITE, TRUE) at its core.
You can use .Interrupt() to wake a sleeping thread (causing ThreadInterruptedException in the code that was calling .Sleep(), which can be caught and handled), so this provides a mechanism to say "sleep until someone prods you". I'm not saying it is necessarily the best mechanism for this, but: it may have uses for you.
In a single-threaded console application, people often use Thread.Sleep as a lazy way to pause the application for some time.
This question raised interesting points about NOT using this approach: Why is Thread.Sleep so harmful
However other than knowing that Sleep blocks the current thread, I don't understand how it works - for instance does it max out the CPU core in a tight loop or does it actually pause the thread?
More importantly to me, how does a console app respond to various app-exit scenarios (CTRL-C, kill, window close button) when caught in the middle of a Sleep? Will it blindly continue executing until the OS force-kills it, or will it behave well?
This is more of an OS question than a C#/.NET related question, but I'll try and answer succinctly.
Thread.Sleep will not spin lock your CPU, instead it will call the appropriate mechanism in the underlying OS to suspend your thread. On windows, that function is described here: https://msdn.microsoft.com/en-us/library/windows/desktop/ms686298(v=vs.85).aspx
Using this normal system call your thread cannot be rescheduled until the timeout has elapsed. Forcefully killing the thread (or the entire process) is then required.
When you hit ctrl+c in cmd.exe, the console spawns a new thread in each process attached to handle the event (Described here: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682541(v=vs.85).aspx). Because of this, your program as a whole will still "behave well" when you hit ctrl+c, but your sleeping thread itself will wind up being killed prematurely.
This is source code of Thread.Sleep method:
[System.Security.SecuritySafeCritical] // auto-generated
public static void Sleep(int millisecondsTimeout)
{
SleepInternal(millisecondsTimeout);
// Ensure we don't return to app code when the pause is underway
if(AppDomainPauseManager.IsPaused)
AppDomainPauseManager.ResumeEvent.WaitOneWithoutFAS();
}
As we can see this method calls Thread.SleepInternal method. In comment about it we can read that this method suspends the current thread for timeout milliseconds. Next, we can read that if timeout == 0 then this method forces the thread to give up the remainder of its timeslice and if timeout equals Timeout.Infinite then no timeout will occur. I recommend you reading about multithreading and application lifecycle (in this case especially suspended).
Links:
https://msdn.microsoft.com/en-us/library/ms900951.aspx
https://msdn.microsoft.com/en-us/windows/uwp/launch-resume/app-lifecycle
How InvokeRequired and Invoke let us make our apps thread safe.
Let's consider such code:
private void ThreadSafeUpdate(string message)
{
if (this.textBoxSome.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(msg);
this.Invoke
(d, new object[] { message });
}
else
{
// It's on the same thread, no need for Invoke
this.textBoxSome.Text = message;
}
}
Is it possible to change state of InvokeRequired after InvokeRequired and before Invoke? If not, then why?
How does Invoking make it thread safe?
If InvokeRequired illustrate is current thread owning control, how would the thread know that it is or it is not the owner.
Let's consider that SomeMethod() is currently running on Thread1. We would like to call it from Thread2. Internally this method updates some field. Does Method.Invoke contain some kind of lock mechanism internally?
What if SomeMethod() takes very long time and we would like to run something other on the control owner thread. Does Invoking lock the owner thread or is it some kind of a background thread safe task?
ThreadSafeUpdate() //takes 5 minutes in Thread2
ThreadSafeUpdate() //after 2 minutes, we are running it in other thread2
ThreadSafeUpdate() //next run from Thread3
I think it is some kind of general pattern which can be implemented outside of winforms, what's its name?
Is it possible to change state of InvokeRequired
Yes, and it is a pretty common occurrence. Either because you started the thread too soon, before the form's Load event fired. Or because the user closed the window just as this code is running. In both cases this code fails with an exception. InvokeRequired fails when the thread races ahead of the window creation, the invoked code fails when the UI thread races ahead of the thread. The odds for an exception are low, too low to ever diagnose the bug when you test the code.
How Invoking make it thread safe?
You cannot make it safe with this code, it is a fundamental race. It must be made safe by interlocking the closing of the window with the thread execution. You must make sure that the thread stopped before allowing the window to close. The subject of this answer.
how would he know that he is or he is not owner.
This is something that can be discovered with a winapi call, GetWindowsThreadProcessId(). The Handle property is the fundamental oracle for that. Pretty decent test, but with the obvious flaw that it cannot work when the Handle is no longer valid. Using an oracle in general is unwise, you should always know when code runs on a worker thread. Such code is very fundamentally different from code that runs on the UI thread. It is slow code.
We would like to call it from Thread2
This is not in general possible. Marshaling a call from one thread to a specific other thread requires that other thread to co-operate. It must solve the producer-consumer problem. Take a look at the link, the fundamental solution to that problem is a dispatcher loop. You probably recognize it, that's how the UI thread of a program operates. Which must solve this problem, it gets notifications from arbitrary other threads and UI is never thread-safe. But worker threads in general don't try to solve this problem themselves, unless you write it explicitly, you need a thread-safe Queue and a loop that empties it.
What's if SomeMethod() takes very long time
Not sure I follow, the point of using threads is to let code that takes a long time not do anything to harm the responsiveness of the user interface.
I think it is some kind of general pattern
There is, it doesn't look like this. This kind of code tends to be written when you have an oh-shoot moment and discover that your UI is freezing. Bolting threading on top of code that was never designed to support threading is forever a bad idea. You'll overlook too many nasty little details. Very important to minimize the number of times the worker thread interacts with the UI thread, your code is doing the opposite. Fall in the pit of success with the BackgroundWorker class, its RunWorkerCompleted event gives a good synchronized way to update UI with the result of the background operation. And if you like Tasks then the TaskScheduler.FromCurrentSynchronizationContext() method helps you localize the interactions.
Usually, no. But it could happen if you're using await between the InvokeRequired check and Invoke call without capturing the execution context. Of course, if you're already using await, you're probably not going to be using Invoke and InvokeRequired.
EDIT: I just noticed that InvokeRequired will return false when the control handle hasn't been created yet. It shouldn't make much of a difference, because your call will fail anyway when the control hasn't quite been created yet, but it is something to keep in mind.
It doesn't make it thread-safe. It just adds the request to the control's queue, so that it's executed the next available time on the same thread the control was created on. This has more to do with windows architecture than with general thread-safety. The end result, however, is that the code runs on a single thread - of course, this still means you need to handle shared state synchronization manually, if any.
Well, it's complicated. But in the end, it boils down to comparing the thread ID of the thread that created the control, and the current thread ID. Internally, this calls the native method GetWindowThreadProcessId - the operating system keeps track of the controls (and more importantly, their message loops).
Invoke cannot return until the GUI thread returns to its message loop. Invoke itself only posts the command to the queue and waits for it to be processed. But the command is run on the GUI thread, not the Invoke-caller. So the SomeMethod calls in your example will be serialized, and the Invoke call itself will wait until the second call finishes.
This should already be answered. The key point is "only run GUI code on the GUI thread". That's how you get reliable and responsive GUI at all times.
You can use it anywhere you've got a loop or a wait on some queue. It probably isn't all that useful, although I have actually used it already a few times (mostly in legacy code).
However, all of this is just a simple explanation of the workings. The truth is, you shouldn't really need InvokeRequired... well, ever. It's an artifact of a different age. This is really mostly about juggling threads with little order, which isn't exactly a good practice. The uses I've seen are either lazy coding, or hotfixes for legacy code - using this in new code is silly. The argument for using InvokeRequired is usually like "it allows us to handle this business logic safely whether it runs in the GUI thread or not". Hopefully, you can see the problem with that logic :)
Also, it's not free thread-safety. It does introduce delays (especially when the GUI thread is also doing some work that isn't GUI - very likely in code that uses InvokeRequired in the first place). It does not protect you from accesses to the shared state from other threads. It can introduce deadlocks. And don't even get me started on doing anything with code that uses Application.DoEvents.
And of course, it's even less useful once you take await into consideration - writing asynchronous code is vastly easier, and it allows you to make sure the GUI code always runs in the GUI context, and the rest can run wherever you want (if it uses a thread at all).
I see the following in Joseph Albahari's Threading book (http://www.albahari.com/threading/)
Thread.Sleep(0) relinquishes the thread’s current time slice
immediately, voluntarily handing over the CPU to other threads.
Framework 4.0’s new Thread.Yield() method does the same thing — except
that it relinquishes only to threads running on the same processor.
Is the context switch happen to some other thread within the same process or among the threads that are waiting to get CPU?
If the answer is the latter, is there any way to do context switch to some other thread that is in wait state in the same process?
I understand that the thread scheduling has been taken care by the operating system. But, got struck with a problem because of Thread.Sleep(0) and trying to find the solution for it.
Editing for more clarity about the problem:
The software has two threads (say A and B) and A will wait for a signal from B for 20 milliseconds and proceed regardless of the signal. A sets the signal and to let the processor continue with B, Thread.Sleep(0) applied as the software is a time critical application where every second maters. For a second both A and B didn't continued and restored (known with the help of the logs). We thought some other process in the same processor got the CPU time slice and now looking for alternatives.
The Thread.Yield method will switch to any thread which is ready to run on the current processor. It doesn't make any distinction about which process that Thread exists in
There is no way to yield to another thread in the same process, even by P/Invoke. Windows simply doesn't support it.
An alternative would be to use some kind of co-operative multitasking, such as TPL and async/await. When you await something, such as the awaitable object returned by Task.Yield(), it enables another task queued with the scheduler to start up. It's also quite a bit more efficient than using Thread.Yield(), but if you're not using it yet this will likely require a large overhaul of your app.
Thread.Yield() will just allow the scheduler to choose another thread within the same process that is ready to run, and resume it at whatever point it was stopped. It has nothing to do with time-slicing among processes, which is a completely different thing. (And rarely of concern unless you're programming the other process(es) as well.)
Note that the Yield() may have no effect at all, if the current thread is the only one able to run. It will just return (relatively immediately) from the Yield() call.
Your question about "context switching to another thread in the same process" is a bit mis-guided. You shouldn't think in those terms. If you need to wait for another thread to finish, use Join. If you need to signal to another thread that it should stop waiting and do something, there are a variety of mechanisms to use for that.
In short, your problem will get worse if you're trying to "outguess" the thread scheduler.
Perhaps you should be more explicit about the problem you're actually having.
Thread is a wrapper around the OS threads. Due to this scheduling of Threads is performed by OS kernel and Yield just a way to tell the kernel, that you want relinquish CPU but still stay runnable (unblocked). A kernel will consider your request as a good point to perform a rescheduling and give the CPU to some other waiting thread. OS is free to give CPU to any waiting thread from the runqueue disregard the process to which it belong. There is no way to affect to the scheduler decision unless it is your own scheduler and you use so called green threads and cooperative multitasking.
In regard to your problem: you need to use explicit synchronization if you want to achieve guaranteed results.
Yielding is a wrong way because it doesn't provide any guaranties to you.
There are a bunch of issues that can appear from its use.
For example, your thread B can simply have not enough time to accomplish its work and to send signal to A before A will be scheduled again, A can be scheduled immediately after Yield onto another CPU core, A even can be rescheduled again before the B will got a chance to be executed. Finally, other application can take a CPU. If you really care about time then raise priorities of both threads, but synchronize them explicitly.
I've been tasked with removing blocking calls from a C# app. Turns out this is a requirement of the environment it'll be running on. I understand the concept of a blocking call, however, I'm not sure where to begin finding existing blocking calls.
So a few questions:
For any given function, how can I tell whether or not it is blocking? Is there any way besides looking up the documentation?
Is there any way to search for blocking in a project or solution? Eg. some plug-in that could tell me?
There's no automatic way I know of to find blocking calls. Most blocking code is used for thread or process synchronization such as lock, Monitor.Enter, Mutex and Semaphore/SemaphoreSlim waits, CountdownEvent and Barrier class use. There's also SpinLock and ReaderWriterLock/ReaderWriterLockSlim locks which block.
There are several Thread calls that are blocking. Thread.Sleep can technically be considered a blocking call, though it lasts a finite amount of time. Thread.Join waits for other threads to finish and is thus blocking.
For and While loops can be considered blocking as they will run until they are done, but usually they will use one of the calls above (especially lock) if they are waiting on a specific variable updated in another thread.
Keep in mind that removing any of these is likely to have a serious negative impact on thread safety.