How to get the reference of TPL task's thread in C#? - c#

When I create a task as
Task task = Task.Factory.StartNew(() => someMethod(args));
in C# 4.0+, how can I get the reference of the thread(s) of this task?
Is it possible that the task is executed in the same thread that created the task or spawn more than one thread?
Update:
The reasons are:
I'd like to identify the task's thread in debugger (and attribute a name for it), etc.
Is created task executed always in separate thread from the one in which a task was created?
Is it one, zero or more than one thread?
Is it executed on a single and the same core?
It is important to know since, for example, I can put to sleep the main thread thinking that I am freezing the background worker
Update:
Useful answer:
Specifying a Thread's Name when using Task.StartNew

Is created task executed always in separate thread from the one in which a task was created?
No, there are certain situations in which the TPL is able to determine that the task can be executed on the same thread that created it, either because the relevant task creation option (or task scheduler) was supplied, or as an optimization because the calling thread would otherwise not have anything to do. You don't really need to worry about this though; it's not like you're going to end up blocking the UI thread because the TPL choose to execute it's code in that context. That won't happen unless you specifically indicate that it should. For all intents and purposes you can assume that this never happens (unless you force it to happen) but behind the scenes, without you ever needing to realize it, yes, it can happen.
Is it one, zero or more than one thread?
By default, tasks are executed in the thread pool. The thread pool will vary in the number of threads it contains based on the workload it's given. It will start out at one, but grow if there is sufficient need, and shrink if that need disappears. If you specify the LongRunning option, a new thread will be created just for that Task. If you specify a custom TaskScheduler, you can have it do whatever you want it to.
Is it executed on a single and the same core?
Potentially, but not assuredly.
It is important to know since, for example, I can put to sleep the main thread thinking that I am freezing the background worker
Putting the main thread to sleep will not prevent background workers from working. That's the whole point of creating the background workers, the two tasks don't stop each other from doing work. Note that if the background workers ever try to access the UI either to report progress or display results, and the UI is blocked, then they will be waiting for the UI thread to be free at that point.

You can use:
System.Threading.Thread.CurrentThread
But as said in the comments, you use the TPL to abstract threading away, so going back to this "low level" is a likely indicator of poor design.

Task.Factory.StartNew() queues the task for execution (see here). The actual thread that executes the task and when it gets executed is up to the TaskScheduler specified (the current TaskScheduler is used if none is specified).
In .Net 4 the default TaskScheduler uses the ThreadPool to execute tasks (see here) so if a ThreadPool Thread queued the task the same thread can possibly execute it later on.
The number of threads is dictated by the ThreadPool.
You shouldn't really care about which core your tasks are executed on.
Queuing a Task for execution will most likely schedule it to be executed on a ThreadPool Thread so you won't be at risk of accidentally putting the main thread to sleep

Related

How can I make a thread wait until another thread is wating (C#)

I have a consumer thread that creates some worker threads. These threads must switch between active and waiting states. When all worker threads are in the waiting states, it means that the current job is done. How can I make the consumer thread wait for all the worker threads to be in the waiting state? I want a behavior very similar to Thread.Join() on all worker threads, however, I want the threads to keep running for the next job. I cannot create new threads because the jobs are in a tight loop and creating new threads is costly.
As far as I am aware there is no mechanism to do what you wish. (Thread.Join but since you can't block that is not an option)
From the info you provided it sounds like your really building a state machine, just across multiple threads.
I would create a Singleton and have that act as a state machine. Threads could signal to the Singleton there status.
It sounds like you have an indeterminate number of threads, so you would need to put the status of each in a collection. I would look here Thread Safe Collections to find the right fit for how you wish to store your state information.
Hope this helps.
Apologies for the brief answer (may expand later), but you probably the WaitHandle.WaitAll method, combined with a ManualResetEvent. You would pass your ManualResetEvent objects into each worker thread when they're created, signal them when they become idle, and pass the entire set of handles into the WaitHandle.WaitAll method to wake the observing thread when they're complete. You can also use the timeout feature of this method if you want to periodically run some kind of task while waiting, or perform some kind of operation if the task is taking too long.
Note that if your worker threads are intended to terminate when the operation is complete (wasn't totally clear if this is the case), it might be more appropriate to spawn them as tasks and use Task.WaitAll instead.
Edit: On a quick re-read, it sounds like you do want to be using tasks rather than trying to re-use full worker threads. Tasks use threads which have been allocated from the thread pool, eliminating that thread creation overhead you were worried about, because the threads will (generally) be ready and waiting for work. You can simply spawn each task and wait for them all to be finished.

Is there a use case where tasks perform worse than threads?

It is considered that tasks are usually better choice than threads as they avoid wasting OS threads and give more programmatic control, but I wonder is there actually a use case where tasks performs worse than threads (so threads should be used instead)?
A task, when is about to be executed, will be executed in a thread context. A thread from the .NET thread pool will be used for the execution of a task. That being said there isn't any comparison between them.
Specifically, a task will be assigned to a thread of the thread pool to be executed, provided that there is a free thread. If there isn't any available thread, then the task will be placed in a queue waiting for one of the used threads to be free and it will be assigned to this thread (if the task is the first in the queue...). If the task will wait a long time in the queue (there is a specific time interval for this, but I don't remember it at this moment), then a new thread will be created, in order to service this task.

Async/Await + FromEvent method

Based on the following question:
General purpose FromEvent method
How do I know which thread in my application the event will return?
I can somehow specify which thread will it continue?
What happens to the thread that is using this feature?
These responses appear to be obvious when I use WPF (Dispatcher/Main/UI Thread), but if I'm working with threads MTA, STA, Reactive, ThreadPool (Task/BackgroundWorker), how can I predict what will happen?
Is there any real benefit than using task.Wait() (if I do not have to worry about locking thread)?
How do I know which thread in my application the event will return?
You don't. You never do with events, unless the documentation for a specific event specifies the that it will be executed from the UI thread, a thread pool thread, etc.
I can somehow specify which thread will it continue?
If you want to run code in a UI thread then marshal to the UI thread in the event handler. If you want to run code in a thread pool thread then add a new task to the thread pool inside of the handler. Both of those tasks add overhead if not needed, so it's usually best to look at the documentation of the event to see which is needed.
However, in the case of the linked question, the whole idea is that you're no longer dealing with an event and an event handler, you're dealing with a Task. So if you add a continuation to the task, the question is where will that continuation run? That is entirely specified by you. You can use the default task scheduler and have it run in the thread pool, you can pass a UI SynchronizationContext to run in the UI thread, or you can just let it run wherever the task you are continuing runs. (Meaning you have no idea what thread will be running it.)
If you're using the task with await, then it will automatically configure the continuation to run in the synchronization context you were in before you started that async operation, which may or may not be the UI thread (but likely is). If you specifically don't want that, then use .ConfigureAwait(false);.
Is there any real benefit than using task.Wait() (if I do not have to worry about locking thread)?
The reason to use an asynchronous task based approach is that you're not blocking threads, particularly thread pool threads (since you've specifically said you're not blocking a UI, which is much worse). Having a thread sitting around doing nothing is a problem, in some environments more than others (such as ASP for a highly active site). By not doing a blocking wait, you aren't consuming those resources.
If you await a Task, then there is a "context" that is captured and used to resume the async method. This "context" is the current SynchronizationContext, unless it is null, in which case it's the current TaskScheduler (which these days is usually the thread pool scheduler).
If you're doing async programming, you should be using await and not Wait. Wait can cause deadlocks, as I explain on my blog.
You may also find my async/await intro helpful.
Using the technique you linked to you cannot predict the thread that this runs on. It might be the thread raising the event, but that is not guaranteed (no, really! It isn't. This is a common misbelief).
So you need to force a switch to whatever thread you want to run on. For example use Task.Run to switch to the thread pool or use TaskScheduler.FromCurrentSynchronizationContext to run on the UI.
If you await the task you are guaranteed to resume in the synchronization context that was set before the await. This is probably what you want.

Can .NET Task instances go out of scope during run?

If I have the following block of code in a method (using .NET 4 and the Task Parallel Library):
var task = new Task(() => DoSomethingLongRunning());
task.Start();
and the method returns, will that task go out of scope and be garbage collected, or will it run to completion? I haven't noticed any issues with GCing, but want to make sure I'm not setting myself up for a race condition with the GC.
Update:
After I answered this question (a long time ago!) I found out that it's not true that Tasks will always run to completion - there's a small, let's say "corner" case, where tasks may not finish.
The reason for that is this: As I have answered previously, Tasks are essentially threads; but they are background threads. Background threads are automatically aborted when all foreground threads finish. So, if you don't do anything with the task and the program ends, there's a chance the task won't complete.
You should always await on tasks. More information can be found on the excellent answer Jon gave me.
Original:
Task are scheduled to the ThreadPool, meaning that they are essentially threads¹ (actually, they encapsulate threads).
From the Thread documentation:
It is not necessary to retain a
reference to a Thread object once you
have started the thread. The thread
continues to execute until the thread
procedure is complete.
So, no, there is no need to retain a reference to it.
Also, the documentation states that the preferred way to create a Task is to use it's factory:
You can also use the StartNew method
to create and start a task in one
operation. This is the preferred way
to create and start tasks if creation
and scheduling do not have to be
separated (...)
Hope it helps.
¹ Accordingly to the documentation:
A task represents an asynchronous
operation, and in some ways it
resembles the creation of a new thread
or ThreadPool work item, but at a
higher level of abstraction.
The task will run to completion. Even if there aren't any other references to it (not being rooted I believe is the term), the thread pool will still hold a reference to it, and prevent it from being Garbage Collected at least (I say at least, because even after it completes, there is no guarantee that it will be Garbage Collected) until completion.

How do I abort CCR threads\tasks?

I want to implement a timeout on the execution of tasks in a project that uses the CCR. Basically when I post an item to a Port or enqueue a Task to a DispatcherQueue I want to be able to abort the task or the thread that its running on if it takes longer than some configured time. How can I do this?
Can you confirm what you are asking? Are you running a long-lived task in the Dispatcher? Killing the thread would break the CCR model, so you need to be able to signal to the thread to finish its work and yield. Assuming it's a loop that is not finishing quick enough, you might choose to enqueue a timer:
var resultTimeoutPort = new Port<DateTime>();
dispatcherQueue.EnqueueTimer(TimeSpan.FromSeconds(RESULT_TIMEOUT),
resultTimeoutPort);
and ensure the blocking thread has available a reference to resultTimeoutPort. In the blocking loop, one of the exit conditions might be:
do
{
//foomungus amount of work
}while(resultTimeoutPort.Test()==null&&
someOtherCondition)
Please post more info if I'm barking up the wrong tree.
You could register the thread (Thread.CurrentThread) at the beginning of your CCR "Receive" handler (or in a method that calls your method via a delegate). Then you can do your periodic check and abort if necessary basically the same way you would have done it if you created the thread manually. The catch is that if you use your own Microsoft.Ccr.Core.Dispatcher with a fixed number of threads, I don't think there is a way to get those threads back once you abort them (based on my testing). So, if your dispatcher has 5 threads, you'll only be able to abort 5 times before posting will no longer work regardless of what tasks have been registered. However, if you construct a DispatcherQueue using the CLR thread pool, any CCR threads you abort will be replaced automatically and you won't have that problem. From what I've seen, although the CCR dispatcher is recommended, I think using the CLR thread pool is the way to go in this situation.

Categories