Does Sleep block program exit? How is it implemented? - c#

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

Related

Does a Task end if you close the application?

So, I basically have this:
public void DoThisThing()
{
Task.Run(() =>
{
while(true)
{
//Do things
}
}
}
The start of the application basically calls the DoThisThing() method and enters it's own loop.
So, if I just close the application, what happens to this task? Does it just end? does it continue forever? Does it go on for a little bit until garbage collection gets it? Does it have a way to know the application ended?
I googled, but I couldn't get a simple answer, and I feel like there definitely is one.
The first question is, how this task is even executed. According to the Documentation:
Queues the specified work to run on the ThreadPool and returns a task or Task handle for that work.
Each programm starts with one Thread, but can start further. This one is the Main Thread, the GUI Thread and a few other names. As a general rule, if that main thread is ending, all others threads it started are canceled too. This is a OS level rule, to avoid Zombie Threads with infinite loops running all over the place.
The ThreadPool and all it's data - including sheduled and running Threads - will be collected by the "End of Application" Garbage Colleciton. If not, there is propably some OS features to make sure they end as well. But I prefer not to mention those OS fallbacks, as we really should not be using them ever. There are for cases when even the GC can no longe run properly (like Programm being killed via Task Manager).
One of the big challenges of Multitasking and -threading is keeping the main Thread alive, but without blocking it so further I/O can happen. In a GUI you have that work done for you (with the EventQueue).
All which is said below is implementation details - FOR WINDOWS - and mostly undocumented behavior. Do not rely on any of the information.
As an implementation detail, this task will most likely be scheduled to execute on a thread pool thread.
If the task has not started by the time the process exit starts, it won't matter it was queued in the first place.
If the task is currently executing, then according to some of the implementation details of process shutdown on Windows eventually only one thread will be executing which will not be the one executing this task. So, it will be forcibly terminated in that case.
If the task has already finished execution, whether through completion or by throwing an exception then there's no thread occupied by it. However, if the exception was left unobserved then the finalizer - should it get a chance to execute - will throw that. Please note that finalizers are also not guaranteed to execute under any circumstances.
This page should have been visible, but Microsoft's latest screw up in revoking access to old MSDN blogs continues.
Similarly, if you can manage to track the first link on this page then do so and read it.
P.S.: Here's the link for Raymond's blog. What you'll find from both sources is that only one thread continues the process shutdown.
The answer depends on the content of the while loop.
If the loop is running some logic that runs entirely within the scope and control of the main program, then closing the application will terminate everything.
However, if the loop is calling some external routines or operating system functions (Example: write to a file, open a network connection, run a command, start a batch job, etc), then closing the application will not terminate everything.
Based on your sample, in brief: Yes
Tasks that are created by TPL (using Task.Run or Task.Factory.StartNew) by default are background threads. So closing application will immediately terminate them.
This post could be helpfull.

Thread.Sleep implementation

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

Deadlock when worker thread tries to invoke something on main thread

I am using an external component which periodically shoots events from a worker thread. In my event handler I use a Dispatcher to invoke some method on the main thread. This works nicely...
private void HandleXYZ(object sender, EventArgs e)
{
...
if(OnTrigger != null)
dispatcher.Invoke(OnTrigger, new TimeSpan(0, 0, 1), e);
}
However, when the program shuts down and the external component Dispose()s, the program sometimes hangs (and can only be seen and killed in the task manager).
When I look at what is happening it looks like "the component" is waiting for the event to return on the main thread (it stays in the Dispose() method), while the worker thread waits for the dispatcher to invoke the mentioned call to the main thread (it hangs in the dispatcher.Invoke-line).
For now I solved the shutdown problem by adding a timeout to the Invoke, which seems to work but feels wrong.
Is there a cleaner way to do something like this? Can I force the main thread to take some time for jobs from other threads before shutting down?
I have tried to "disconnect" the event before shutting down, but that does not help, because the dispatcher is(could be) already waiting, when the program start to shut down...
PS: external component means here that I do not have access to the source code...
Yes, this is a common source of deadlock. It hangs because the dispatcher exited the dispatcher loop it won't respond to Invoke requests anymore. A quick cure is to use BeginInvoke instead, it doesn't wait for the invoke target to finish executing. Another quickie is to set the worker thread's IsBackground property to True so the CLR will kill it.
These are quick fixes and they may well work for you. Certainly on your dev machine, but if you have a nagging feeling that it may still go wrong then you're right, not observing a deadlock or threading race does not prove they are not present. There are two "good" ways to do it completely safely:
don't allow the main thread to exit until you are sure that the worker thread terminated and can no longer raise events. This answer shows the pattern.
terminate the program forcefully with Environment.Exit(). This is very crude but very effective, a sledgehammer you'll only reach for when you have a heavily threaded program where the UI thread is only second citizen. Odd as this may sound as a suitable approach, the new C++ language standard has elevated it to a supported way to terminate a program. You can read more about it in this answer. Do note how it allows for cleanup functions to be registered, you'll have to do something similar with, say, the AppDomain.ProcessExit event. Focus on the first bullet before you do this.
As for the event subscriptions, it is indeed a good idea to clean them up when you know that a particluar object is not needed anymore. Otherwise you would risk creating memory leaks. You might also want to have a look at the weak event pattern (MSDN).
Regarding the deadlock itself, without knowing your code, we can only guess.
I do not see the HandleXYZ() as a culprit, I would rather check your IDisposable() implemntaion. Have a look at the MSDN documentation and compare it to your implementation.
I suppose that somewhere in there in your implementation some method calls are made that depend on the timing of the GarbageCollector, which is indeterministic: Sometimes it may work out in your case, sometime it may not.

ensuring all threads have stopped after c# integration tests

In some of my integration tests I start multiple threads and wanted to ensure that when the integration test finishes (even if it fails) the thread will be cleaned up. Can anyone recommend an elegant way to do this?
Thanks
EDIT: Thanks for everyone's answers - just to clarify, 'cleaned up' was referring to when the testing threads stops and some of the other threads in a test haven't QTAgent (the testing process) was giving an error.
Make sure you keep the Thread object for every thread you create
Call Thread.Join() on all of them at the end of the test, after setting appropriate termination signals. If any thread doesn't terminate quickly enough, this should cause the test to fail even if the test would otherwise have passed.
It's impossible to answer this in more detail without knowing more about your application and test architecture.
If you are using .Net 4.0, and you know how many threads you are going to launch, you could use a CountdownEvent. Then in each thread, have a try/finally block that will set the event. In your cleanup code, wait on the event. You can add a timeout if you like and use that to indicate some error condition.
you can use task in C# 4 and use a cancellation token and/ or handle the end of the thread. see http://msdn.microsoft.com/en-us/library/dd460717.aspx
Using Thread.Join() will block your current thread until the thread you are calling join on exits. Before joining, you can signal the other threads to exit in a variety of fashions depending on the circumstances.
Calling Thread.Abort() will raise an abort exception in the target thread which will typically bring it to a stop unless you explicitly do something to prevent that. Although aborts aren't exactly elegant.
Setting Thread.IsBackground to true on your test threads will make sure they don't keep your process alive when your main threads exit. When the process exits, your background threads will take care of themselves automatically.
Personally, most of my test threads tend to be in the following pattern:
private static readonly ManualResetEvent m_ThreadsShouldExit = new ManualResetEvent(false);
private static void SomeThreadBody()
{
while(!m_ThreadsShouldExit.WaitOne(0))
{
DoSomething();
}
}

Best Way to wake a thread up to quit? C#

I spawn a thread (only one) to do some work and it pretty much takes care of itself not accessing any data outside of the tread except calling callback() to see if the user wants to quit (also sends a status report back to the main thread to display in the GUI).
When the close closes the exe i would like to wake up the thread and have it quit, whats the best way of doing this? The callback already says if the user wants to quit so now the issue is using Thread.Sleep and waking it up prematurely so it can quit instead of having the process live for another few seconds or minutes. This feature would be nice for stop to exit more quickly.
Another approach would be as follows:
Have a ManualResetEvent in your program and call Set when you want the thread to finish up and close down. Instead of calling Thread.Sleep on your work thread, call event.WaitOne and pass in a TimeSpan object. If the event is signalled, your worker thread will wake up before the timeout occurs - WaitOne will return true.
Use a BackgroundWorker or set your thread's IsBackground property to true, then it won't keep your application open.
I'd recommend the BackgroundWorker, but the latter is a quick fix.
Update
Original poster changed his requirements after posting the question (see comments attached to this question). Update to answer follows:
If you want to stop a background operation without ending the application, please see Background worker's CancelAsync method. Also, don't use Thread.Sleep - use a WaitHandle and call WaitOne on what you need to wait for.
I have to agree with Mark. The only thing clear about your question is that you need to reexamine your threading strategy.
You say you have a thread doing work but then you say you want to wake it up?
Is the thread waiting for work? If so, sleep in shorter cycles and check for exit more often or use a reset event. The best way to wake a thread up is to not put it to sleep. Do what you have to do and exit. Always check for interrupt signals, in whatever form you implement them, before starting any long running operations, and again, if you must sleep the thread, do it in short cycles.
Is the thread busy and you want to interrupt it? You may have no choice but to kill it if you cannot instrument it such that it can respond to interrupt signals in a timely fashion.

Categories