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.
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 have an issue (maybe it's not an issue) where I create a thread, it does it's work, then I finish and the working thread (that I created the task with) is exited. In my mind I see everything being completed and the new thread I created should have exited. But for some reason the thread does NOT actually exit for a few more seconds (about 5-8 seconds) after the function has completed. I can tell by watching the output window for lines like...
The thread 'threadTaskWorker16' (0xdd8c) has exited with code 0 (0x0).
Here is how I create the new thread...
public bool CreateNewTask()
{
Task<TaskInfo> taskWork = Task.Factory
.StartNew(() => threadTaskWorker(taskParams),
CancellationToken.None,
TaskCreationOptions.None,
TaskScheduler.Default)
.ContinueWith(task => threadTaskComplete(task.Result));
}
private TaskInfo threadTaskWorker(TaskInfo taskParams)
{
Thread.CurrentThread.Name = "threadTaskWorker" + Thread.CurrentThread.ManagedThreadId;
Debug.WriteLine("Thread " + Thread.CurrentThread.ManagedThreadId + " has started it's long and exhausting process that would have hung the GUI out to dry...");
for (int i = 0; i < 50; i++)
{
Thread.Sleep(3000);
}
Debug.WriteLine("Thread has completed it's work.");
}
private TaskInfo threadTaskComplete(TaskInfo taskParams)
{
Debug.WriteLine("Thread " + Thread.CurrentThread.ManagedThreadId + " has been destroyed.");
}
So my question is, why does it take so long to actually EXIT the thread after the custom function has completed? I was thinking about somehow killing the thread at the end of my function but that seems like I would be going about it the wrong way. Is there a way to make the thread exit sooner?
Second question, Is there a way to fire an event so I know when the thread actually exits (like when I see it in the output window)?
You are seeing the effect of the ThreadPool. Since creating new threads is computationally expensive, Tasks will keep a "pool" of threads around and reuse them for multiple tasks if they are not in use. Only after the Pool sees that it has extra unused threads will it actually physically kill the thread, showing that message in the output window.
Your threadTaskDestroyed should be getting called as soon as the task completes, no need for any kind of event. If you really want more controll, look at some of the synchronization objects like Mutex or AutoResetEvent. If you are using Tasks you shouldn't have to worry about managing threads though, it's all handled for you and "does the right thing" in the majority of the cases.
See this MSDN article for more information https://msdn.microsoft.com/en-us/library/0ka9477y(v=vs.110).aspx
BTW, NEVER kill a thread. You will leave things in a VERY unpredictable state. http://www.interact-sw.co.uk/iangblog/2004/11/12/cancellation
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.
(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 c# console application which has some threads to do some work (download a file).
each thread may exit the application at any time any where in application, but I'll show a proper message on console. It's possible to track them but it doesn't make sense to me. I want simply check thread count or something like that to find out which one is the last thread and do something when it is exiting.
What's the best practice to do so ?
pseudo code:
if (lastThread)
{
cleanUp();
Console.ReadLine();
}
Thanks
This is one place where using the new Task Parallel Library can make life much easier. Instead of creating threads, and spinning work up on the thread, you can use multiple tasks:
var task1 = Task.Factory.StartNew( () => DoTaskOneWork() );
var task2 = Task.Factory.StartNew( () => DoTaskTwoWork() );
var task3 = Task.Factory.StartNew( () => DoTaskThreeWork() );
// Block until all tasks are done
Task.WaitAll(new[] {task1, task2, task3} );
cleanUp(); // Do your cleanup
If the "tasks" are just downloading a bunch of individual files, you could even make this simpler using PLINQ:
var fileUrls = GetListOfUrlsToDownload();
fileUrls.AsParallel().ForAll( fileUrl => DownloadAndProcessFile(fileUrl) );
cleanUp(); // Do your cleanup
A design where you lose track of your threads is not ideal.
Depending on how you spawn them it ought to be possible to track the status of each by associating some per-thread signalable object, then WaitAll on those signalable objects.
Each signalable object in turn should get signaled as its thread exits. When they are all signaled, you know the threads are all dead and you close down clean. You have to make sure that abnormal conditions in your threads do not result in that thread's associated signalable object remaining unset, or your WaitAll will never return. This means exceptions typically - could use try...finally to ensure the objects get signaled.
Your new pseudocode is
foreach (workitem in list of work)
start up thread associated with a ManualResetEvent or similar
WaitAll for all events to be signalled
cleanup
Your main thread should join with all your worker threads and block while they are running. Then when all threads are complete it performs the cleanup code and then quits.
Alternatively you can use a WaitHandle such as as a ManualResetEvent per thread and wait for all of them to be signalled.