I believe, while unlikely, that it is possible for a Task queued up using Task.Run() to end up running on the Main thread.
I'm concerned that (in my WPF app), If I am using App.Current.Dispatcher.Invoke(), or similar, inside this Task, I will cause a deadlock.
Is this a valid fear? If so, is there a way to prevent this from happening (without checking the current thread *isnt* the main thread).
Thanks
I believe, while unlikely, that it is possible for a Task queued up using Task.Run() to end up running on the Main thread.
You believe incorrectly: this is not possible. Task.Run dispatches to the ThreadPool, not the UI thread's dispatcher. The two are entirely separate.
I'm concerned that (in my WPF app), If I am using App.Current.Dispatcher.Invoke(), or similar, inside this Task, I will cause a deadlock.
You should avoid using Invoke anyway, because of the risk of deadlocks. The risk is that the UI thread is waiting for your thread to do something, and by synchronously waiting for the UI thread to be free enough to process your message, you're risking deadlock.
You can normally use BeginInvoke instead (having a background thread whose progress depends on what the UI is doing is normally bad design), but you rarely need this when you're using await and Progress<T>/IProgress<T>.
Related
I read here:
.NET async, can a single thread time-slice between tasks?
that, unless you explicitly use async/await, tasks will not "time-slice" on the same thread in the backend thread-pool. Is this guaranteed? Or merely a side effect of the current implementation of the TPL?
If not guaranteed, it would cause problems with using lock():
Consider two Tasks which access a method that locks on a full SerialPort transaction (send a message and receive, or timeout) before releasing. If time-slicing occurs on the same thread and the SerialPort access is slow enough, the lock would fail to do its job (letting both calls through, because they are technically on the same thread).
Yes, as long as you don't do anything that makes (some parts of) your code execute on another thread (await, Task.Run(), Task.ContinueWith(), Thread, …), then it's safe to use lock or another thread-based synchronization mechanism.
One possible exception is if you have a custom TaskScheduler (e.g. TaskScheduler.FromCurrentSynchronizationContext()) and you somehow make that scheduler try to execute more Tasks while your Task is still executing (e.g. something like Application.DoEvents()). In that case, your Task still won't move to another thread, but it may be paused while another Task executes on the same thread. But this situation should be exceedingly rare.
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
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.
It's pretty clear that using "await" to offload a Task from a UI thread is a great thing - the UI thread can then get back to handling Windows messages.
But let's say you start the awaited Task with Task.Run, which launches your code on a thread from the ThreadPool. Is there any value (any technically can it even be done?) to do an "await" in that code?
I'm tempted to say "no". Why would you want to offload work from a ThreadPool thread-- what else does it have to do except process the original task assigned to it?
Now, I would be REALLY impressed if someone replied and said that if I do an await, the ThreadPool thread can actually be "released" to the pool and used elsewhere, all while my async work continues...
Michael
technically can it even be done?
Yes. The resulting continuation will be run on a (likely) different ThreadPool thread, since there is no current SynchronizationContext. However, the mechanism works well.
Is there any value to do an "await" in that code?
Yes, there is. See below.
Why would you want to offload work from a ThreadPool thread-- what else does it have to do except process the original task assigned to it?
You could free up the thread to do other work. ThreadPool threads are a limited, finite resource.
Now, I would be REALLY impressed if someone replied and said that if I do an await, the ThreadPool thread can actually be "released" to the pool and used elsewhere, all while my async work continues..
Yes, this is effectively what happens.
Aside from the abililty to release the task, there is a another huge advantage to doing this - you can use the same method, with the same code, whether you're on the ThreadPool or a thread with a synchronization context. The ability to reuse the same code is hugely valuable, as well.
I'm making several HttpWebRequest.BeginGetResponse calls, and in the callback method of the BeginGetResponse, I'm invoking an EventHandler. In the EventHandler, there is logic to test if the download was successful. If not, it tries to redownload the Html. I'm noticing lots of threads being generated especially when there are errors. So, on which thread do the Async Callbacks run?
Is there anyway I can invoke the EventHandler on the original thread? If that is not posible, can I invoke it on the UI thread?
Thanks!
Callbacks are made on a threadpool thread. There is no mechanism in .NET to make code run on a specific thread. That is very hard to come by, you can't just interrupt a thread while it is busy and make it run some code. That causes horrible re-entrancy problems that a lock cannot solve.
A thread must be in an idle state, not actively mutating the state of the program. There's one kind of thread that behaves that way, the UI thread in a Winforms or WPF app. That's also the thread that has to deal with objects that are fundamentally thread-unsafe, anything related to the UI. This is not a coincidence.
Both class libraries make it possible to marshal a call from a worker thread to the UI thread, specifically to help getting the UI updated in a thread-safe way. In Winforms you use Control.Begin/Invoke(), in WPF you use Dispatcher.Begin/Invoke(). BackgroundWorker is a handy class to get this done without explicitly managing the marshaling. But isn't suitable for I/O completion callbacks.
What do you mean by "on the original thread"? Which original thread? You can marshal to the UI thread using Control.BeginInvoke or Dispatcher.BeginInvoke. You can't marshal to an arbitrary thread - it has to have something like a message pump waiting for work.
As for which thread HttpWebRequest async callbacks are executed on - I would expect either a general thread pool worker thread, or possibly an IO completion port thread.
Using the Begin/End Async pattern, be aware that it's possible for many kinds of tasks to complete on the thread they were called from. When you call BeginXXX, it returns a boolean that signifies if the task was completed on the calling thread or not.
The basic answer is, it could be any thread.
If you are using WPF you can use the Dispatcher to invoke your logic on the UI thread.
Otherwise, (if not in WPF) you could use a SyncrhronizationContext to accomplish the same thing.