Why does a Thread (which I set IsBackgroundthread to True) is not running with the threadpool Threads ?
/*1*/ volatile bool r = false;
/*2*/ var g= new Thread(() => r=Thread.CurrentThread.IsThreadPoolThread );
/*3*/ g.IsBackground = true;
/*4*/ g.Start();
/*5*/ g.Join();
/*6*/ Console.WriteLine(r); //false
While this code (obviously) does run at a threadpool thread ?
Task.Factory.StartNew(()=>Console.Write(Thread.CurrentThread.IsThreadPoolThread)); //true
Console.ReadLine();
p.s.
(I know that Task are (by default)run at a background threads and they run in a threadpool , but my question is about a similar situation where I set a thread to run at background).)
The ThreadPool is a pool of dedicated threads managed by the runtime.
User-created background threads are not part of the threadpool.
In other words, all thread-pool threads are background threads, but not all background threads are thread-pool threads.
The IsBackground property does not do what you think it does. It is merely a flag that tells the CLR whether it is okay to abort the thread when the non-background threads complete, including the main thread of the program. If it is false, the default value, then the CLR won't interfere with the thread, allowing it to complete. Setting it to true invokes the equivalent of Thread.Abort(), minus the ability for the thread to do anything about it or be notified about it. A rude abort.
The thread created by the Thread class is never pooled, unless some kind of custom CLR host is used which is very rare. Common ways to create a threadpool thread are ThreadPool.QueueUserWorkItem,() BackgroundWorker, a delegate's BeginInvoke() method and the Task class.
Related
I'm trying to understand threads in C#.
Whenever I pass the method in Parallel.Invoke() it create a new thread or use thread from a thread pool?
By default the Parallel.Invoke uses the current thread, and threads from the ThreadPool. That's because the default value of the ParallelOptions.TaskScheduler property is TaskScheduler.Default, and the TaskScheduler.Default schedules work on the ThreadPool.
TaskScheduler defaultScheduler = new ParallelOptions().TaskScheduler;
Console.WriteLine($"defaultScheduler: {defaultScheduler}");
Console.WriteLine("defaultScheduler == TaskScheduler.Default: " +
(defaultScheduler == TaskScheduler.Default));
Output:
defaultScheduler: System.Threading.Tasks.ThreadPoolTaskScheduler
defaultScheduler == TaskScheduler.Default: True
Parallel.Invoke(
() => Console.WriteLine(Thread.CurrentThread.IsThreadPoolThread),
() => Console.WriteLine(Thread.CurrentThread.IsThreadPoolThread),
() => Console.WriteLine(Thread.CurrentThread.IsThreadPoolThread)
);
Output:
False
True
True
Online demo.
Parallel.Invoke method uses a thread pool to execute the provided methods concurrently. A thread pool is a collection of pre-allocated threads that can be used to execute tasks concurrently. When you call Parallel.Invoke, it creates tasks for each of the provided methods and adds them to the thread pool for execution. The thread pool will then assign the tasks to threads in the pool and execute them concurrently.
Creating new threads can be a time-consuming operation. Using a thread pool allows you to reuse existing threads rather than creating new ones, which can save resources and improve performance.
Using a thread pool allows you to easily control the number of concurrent threads, as the pool has a fixed size. This can help prevent overloading the system with too many threads, which can negatively impact performance.
Here's how it works in steps.
You call Parallel.Invoke().
After that a new task or tasks gets created for the work that you want to execute.
Those tasks get scheduled by TPL for execution.
TPL schedules these tasks for execution by assigning threads from the thread pool.
returns when all the tasks have finished executing.
So to answer your question Parallel.Invoke() does not create a new thread or get it from the thread pool. It's handled by TPL
If I've missed anything let me know.
This is my understanding of the topic.
I need to control one thread for my own purposes: calculating, waiting, reporting, etc...
In all other cases I'm using the ThreadPool or TaskEx.
In debugger, when I'm doing Thread.Sleep(), I notice that some parts of the UI are becoming less responsible. Though, without debugger seems to work fine.
The question is: If I'm creating new Thread and Sleep()'ing it, can it affect ThreadPool/Tasks?
EDIT: here are code samples:
One random place in my app:
ThreadPool.QueueUserWorkItem((state) =>
{
LoadImageSource(imageUri, imageSourceRef);
});
Another random place in my app:
var parsedResult = await TaskEx.Run(() => JsonConvert.DeserializeObject<PocoProductItem>(resultString, Constants.JsonSerializerSettings));
My ConcurrentQueue (modified, original is taken from here):
Creation of thread for Queue needs:
public void Process(T request, bool Async = true, bool isRecurssive = false)
{
if (processThread == null || !processThread.IsAlive)
{
processThread = new Thread(ProcessQueue);
processThread.Name = "Process thread # " + Environment.TickCount;
processThread.Start();
}
If one of the Tasks reports some networking problems, i want this thread to wait a bit
if (ProcessRequest(requestToProcess, true))
{
RequestQueue.Dequeue();
}
else
{
DoWhenTaskReturnedFalse();
Thread.Sleep(3000);
}
So, the question one more time: can Thread.Sleep(3000);, called from new Thread(ProcessQueue);, affect ThreadPool or TaskEx.Run() ?
Assuming that the thread you put on sleep was obtained from thread pool then surely it does affect the thread pool. If you explicitly say that the thread should sleep then it cannot be reused by the thread pool during this time. This may cause the thread pool to spawn new threads if there are some jobs awaiting to be scheduled. Creating a new thread is always expensive - threads are system resources.
You can however look at Task.Delay method (along with async and await) that suspends executing code in a more intelligent way - allowing the thread to be reused during waiting.
Refer to this Thread.Sleep vs. Task.Delay article.
Thread.Sleep() affects the thread it's called from, if you're calling Thread.Sleep() in a ThreadPool thread and trying to queue up more it may be hitting the max count of ThreadPool threads and waiting for a thread to finish before executing another.
http://msdn.microsoft.com/en-us/library/system.threading.threadpool.setmaxthreads.aspx
No, the Thread.Sleep() is only on the current thread. Thread.Sleep(int32) documentation:
The number of milliseconds for which the thread is suspended.
(the following items has different goals , but im interesting knowing how they "PAUSEd")
questions
Thread.sleep - Does it impact performance on a system ?does it tie up a thread with its wait ?
what about Monitor.Wait ? what is the difference in the way they "wait"? do they tie up a thread with their wait ?
what about RegisteredWaitHandle ? This method accepts a delegate that is executed when a wait
handle is signaled. While it’s waiting, it doesn’t tie up a thread.
so some thread are paused and can be woken by a delegate , while others just wait ? spin ?
can someone please make things clearer ?
edit
http://www.albahari.com/threading/part2.aspx
Both Thread.Sleep and Monitor.Wait put the thread in the WaitSleepJoin state:
WaitSleepJoin: The thread is blocked. This could be the result of calling
Thread::Sleep or Thread::Join, of requesting a lock — for example, by
calling Monitor::Enter or Monitor::Wait — or of waiting on a thread
synchronization object such as ManualResetEvent.
RegisteredWaitHandle is obtained by calling RegisterWaitForSingleObject and passing a WaitHandle. Generally all descendants of this class use blocking mechanisms, so calling Wait will again put the thread in WaitSleepJoin (e.g. AutoResetEvent).
Here's another quote from MSDN:
The RegisterWaitForSingleObject method checks the current state of the
specified object's WaitHandle. If the object's state is unsignaled,
the method registers a wait operation. The wait operation is performed
by a thread from the thread pool. The delegate is executed by a worker
thread when the object's state becomes signaled or the time-out
interval elapses.
So a thread in the pool does wait for the signal.
Regarding ThreadPool.RegisterWaitForSingleObject, this does not tie up a thread per registration (pooled or otherwise). You can test this easily: run the following script in LINQPad which calls that method 20,000 times:
static ManualResetEvent _starter = new ManualResetEvent (false);
void Main()
{
var regs = Enumerable.Range (0, 20000)
.Select (_ => ThreadPool.RegisterWaitForSingleObject (_starter, Go, "Some Data", -1, true))
.ToArray();
Thread.Sleep (5000);
Console.WriteLine ("Signaling worker...");
_starter.Set();
Console.ReadLine();
foreach (var reg in regs) reg.Unregister (_starter);
}
public static void Go (object data, bool timedOut)
{
Console.WriteLine ("Started - " + data);
// Perform task...
}
If that code tied up 20,000 threads for the duration of the 5-second "wait", it couldn't possibly work.
Edit - in response to:
"this is a proof. but is there still a single thread which checks for
signals only ? in the thread pool ?"
This is an implementation detail. Yes, it could be implemented with a single thread that offloads the callbacks to the managed thread pool, although there's no guarantee of this. Wait handles are ultimately managed by operating system, which will most likely trigger the callbacks, too. It might use one thread (or a small number of threads) in its internal implementation. Or with interrupts, it might not block a single thread. It might even vary according to the operating system version. This is an implementation detail that's of no real relevance to us.
While it's true RegisterWaitForSingleObject creates wait threads, not every call creates one.
From MSDN:
New wait threads are created automatically when required
From Raymond Chen's blog:
...instead of costing a whole thread, it costs something closer to (but not exactly) 1/64 of a thread
So using RegisterWaitForSingleObject is generally preferable to creating your own wait threads.
Thread.Sleep and RegisteredWaitHandle work at different levels. Let me try and clear it up:
Processes have multiple threads, which execute simultaneously (depending on the OS scheduler). If a thread calls Thread.Sleep or Monitor.Wait, it doesn't spin - it is put to WaitSleepJoin state, and the CPU is given to other threads.
Now, when you have many simultaneous work items, you use a thread pool - a mechanism which creates several threads, and uses its own understanding of work items to dispatch calls to its threads. In this models, worker threads are called from the thread pool dispatcher to do some work, and then return back to the pool. If a worker thread calls a blocking operation - like Thread.Sleep or Monitor.Wait - the this thread is "tied up", since the thread pool dispatcher can't use it for additional work items.
I'm not familiar with the actual API, but I think RegisteredWaitHandle would tell the thread pool dispatcher to call a worker thread when needed - and your own thread is not "tied up", and can continue its work or return to the thread pool.
ThreadPool.g RegisterWaitForSingleObject does call in its native implementation ultimately
QueueUserAPC. See rotor sources (sscli20\clr\src\vm\win32threadpool.cpp(1981)). Unlike Wait Thread.Sleep your thread will not be put to a halt when you use RegisterWaitForSingleObject.
Instead for this thread a FIFO queue with user mode callbacks is registered which will be called when the thread is in an alertable state. That means you can continue to work and when your thread is blocked the OS will work on the registered callbacks giving your thread do to the opportunity to do something meaningful while it is waiting.
Edit1:
To complete the analysis. On the thread that did call RegisterWaitForSingleObject a callback is called on the thread when it is in an alertable state. Once this happens the the thread that did call RegisterWaitForSingleObject will execute a CLR callback that does register another callback which is processed by a thread pool callback wait thread which is only there to wait for signaled callbacks. This thread pool callback wait thread will then check in regular intervals for signaled callbacks.
This wait thread does finally call QueueUserWorkItem for the signalled callback to be executed on a thread pool thread.
I have a Backgroundworker whose purpose is to run jobs sequentially in the background. Now one job is implemented in multithreading way. That mean, the Backgroundworker will create several threads. I use Task Parallel Library so I use the Task.Factory.StartNew to create multiple Tasks.
After the tasks are run, the Backgroundworker waits all of them to finish.
Now I print the Backgroundworker's ManagedThreadID and all the tasks' ManagedThreadIDs. I found that the BackgroundWorker's ManagedThreadID is always the same as the first task's ManagedThreadID. I think this shouldn't happen so I cannot explain. I think the Backgroundworker's thread must be different to all the tasks it creates so the ManagedThreadIDs must be all different from each other.
Can anyone explain why this scenario happens? Thank you very much.
Edit:
The code is similar to this:
Backgroundworker.Run(){
// Print Thread.CurrentThread.ManagedThreadID.
var task = Task.Factory.StartNew(action1); // action1, action2 also print ManagedThredID.
taskList.Add(task);
task = Task.Factory.StartNew(action2);
taskList.Add(task);
... // Several other tasks.
foreach(var task in taskList) task.Wait();
}
You will find that one task has the same ManagedThreadID as the Backgroundworker.
I would go on a limb here and guess that the TPL is smart enough to reuse the BackgroundWorker thread. Since the worker waits for all tasks to complete running one task in the same thread is probably an optimization.
From further investigation, what you are seeing is a result of the expected behaviour of the Task.Wait method. You can read more at Task.Wait and "Inlining" on the Parallel Programming Team blog.
If the Task being Wait’d on has
already started execution, Wait has to
block. However, if it hasn’t started
executing, Wait may be able to pull
the target task out of the scheduler
to which it was queued and execute it
inline on the current thread.
The Background worker draws threads from the thread pool as well as TPL. What might happen is that the background worker is started, it draws a thread from the pool and fires TPL threads and returns immediately the thread to the pool. By the time TPL's first task is executed TPL draws a thread from the pool and it happens that it picks the same thread as the one once used by the background worker.
Of course that's just a supposition which cannot be verified because you haven't shown your code.
What you have stumbled upon is of course not a problem but a feature (optimization): The TPL is re-using threads as much as it can.
When you create a Task it is not immediately/permanently associated with a Thread. A Task is a Job that is put in a Queue and the Queue(s) are serviced by worker threads. So it could be that the Bgw Task is suspended and its thread returned to the pool, or more directly it could be done by the Wait():
// thread A
var t1 = Task.Startnew(...);
var t2 = Task.Startnew(...);
t1.Wait(); // Thread A is idle/available so Wait can execute t1
t2.Wait();
Use TaskCreationOptions.LongRunning to avoid re-cycling the background worker.
I have an application that uses 20 threads. It's an email client that uses threads to mail from.
Currently the threads are created in the main thread. But I am wondering, what if I want to cancel the whole operation? The only way I can see of doing it is killing the main thread ... thus ending the program.
Would I have to create a thread that encapsulates the threads for mailing so I can kill the encapsulating thread?
I am currently using BackgroundWorker by the way and it's a WF application.
If you are using a BackgroundWorker then you already have all of the infrastructure you need to cancel the operation. Simply set WorkerSupportsCancellation to true on the BackgroundWorker, and invoke the worker's CancelAsync method when you want to cancel.
Obviously you have to write the worker code to honour the cancellation. You do this by checking the CancellationPending property of the BackgroundWorker.
MSDN has an example of using this property.
Note - I am a bit confused by the combination of BackgroundWorker and 20 threads; a BackgroundWorker only uses one thread by itself. Are you spinning off 20 BackgroundWorkers? If so, how do you ensure that they're properly disposed? If you need that much concurrency in a Winforms app then it's better to use asynchronous delegates or the Thread Pool.
If you are creating actual threads, one common way of implementing a cancellation flag is to use a ManualResetEvent. If you wait on this event with zero timeout, it acts as a thread-safe status flag. An example usage would be:
ManualResetEvent cancelEvent = new ManualResetEvent(false);
for (int i = 0; i < 20; i++)
{
ThreadPool.QueueUserWorkItem(s =>
{
// Do some work
if (cancelEvent.WaitOne(0, true))
return;
// Do some more work
// etc.
});
}
Then at some point later if you write cancelEvent.Set(), every worker will stop its work as soon as it hits the status check.