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.
Related
I just would like to ensure I understood well the differences between async await and Task.run or Task.whenall
So async await is to process asynchronous methods. It means that there is an order of processing implied.
I run a long processing without blocking the main thread and I wait for the result to continue.
For Task.Run and Task.Whenall there is a new notion with multithreading. It means that I can launch a long process on a new thread and it doesn't wait to complete to continue the code. The code is on a new thread. On this thread then I can await method.
So If I clearly understood I decided to use async await for long processes which implies an order of execution on main thread.
And I use Task.run for thread to run in parrallel and process independently.
Is it the good way and is my understanding good?
Thanks,
Your understanding of async/await and Task.Run is mostly correct.
Task.Run allows you to easily run some code on a ThreadPool thread and avoid blocking current thread. Creating multiple Tasks or using Parallel class allows you take adventage of multiple CPU cores to do some work faster.
When using async/await you can do some work once your task has completed. Thanks to SynchronizationContext code after await can be executed back on your original thread, although it is not always the case. For exaple console application has no SynchronizationContext.
One important thing to remember is that async/await is great for I/O bound work while Task.Run is good for CPU bound work. Reason behind this is that when you await some I/O bound operation, like sending data over network, you don't waste any thread on just waiting for such operation to complete. You can read more about that here.
Yes, the Task.Run method is an easy way to offload work to a background thread. The worker threads are provided by the ThreadPool class. Learning a bit about this class is a good idea, to know what happens when the pool becomes starved, and what you can do if you anticipate this to happen (using the SetMinThreads proactively is an option).
Using the Task.Run is more convenient than working with Thread instances directly. Tasks have a strongly-typed Result, have an Exception property, can be awaited asynchronously, can be combined with other tasks, and can be wrapped in other tasks with extra functionality (for example wrapping a task in a cancelable wrapper.
I wonder whether existing I/O bound APM calls in .net API (BeginGetResponse, BeginRead, etc.) uses a thread from threadpool or uses the current thread until the callback. I know that it is "async" all the way down to the hardware/network card. I also know that the callback is executed on threadpool. My question is that: All contents of BeginGetResponse are executed on Threadpool or the contents until waiting for I/O are executed on current thread; then the rest is executed on threadpool.
I hope that the question is clear. I really wonder how BeginGetResponse is implemented underhood.
APM is more general mechanism. But the cases you are talking about use the operating system's support for I/O completion ports. The general idea is that your main thread calls the BeginXxx() method. Under the hood, it calls ThreadPool.BindHandle(), that sets up the plumbing to get the port to automatically start a TP thread when the I/O operation completes. That thread calls your callback method.
Core idea that no thread is waiting while the I/O operation takes place.
This is supported for MessageQueue, FileStream, PipeStream, Socket, FileSystemWatcher, IpcChannel and SerialPort.
BeginXxx execute on the current thread. You can easily verify this for yourself using e.g. Reflector. Moreover, sometimes the callback is executed on the current thread too. One case is if an error occurs early, and another is when the actual asynchronous I/O operation blocks — this happens sometimes, as asynchronous I/O is not guaranteed not to block.
The IAsyncResult approach using worker pool threads is available only for some tasks. Like FileIO (not directory enumeration), LDAP query (v2.0), ADO .net queries.
If you have it and can take the complexity, use the APM. They are usually built by .net folks as it takes some complexity.
Otherwise, use hand built if you think you will get speed.
Using explicit threads gives you more control. Specifically, you can choose to have foreground threads, which will keep your application "alive" after the main thread returns from Main. Explicit threads can also specify their COM threading apartment.
The general rule is to use the threadpool when you have a queue of work items to do, and use an explicit thread when you have an architectural need for them.
Many operations use IO completion ports.
This means that no thread is used while waiting for the operation. Once the operation is complete, the callback is called on a thread-pool thread or using some other synchronization context.
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.
In MSDN, there is a paragraph like this:
The async and await keywords don't cause additional threads to be
created. Async methods don't require multithreading because an async
method doesn't run on its own thread. The method runs on the current
synchronization context and uses time on the thread only when the
method is active. You can use Task.Run to move CPU-bound work to a
background thread, but a background thread doesn't help with a process
that's just waiting for results to become available.
But it looks I need little more help with the bold text since I am not sure what it exactly means. So how come it becomes async without using Threads?
Source: http://msdn.microsoft.com/en-us/library/hh191443.aspx
There are many asynchronous operations which don't require the use of multiple threads. Things like Asynchronous IO work by having interrupts which signal when data is available. This allows you to have an asynchronous call which isn't using extra threads - when the signal occurs, the operation completes.
Task.Run can be used to make your own CPU-based async methods, which will run on its own separate thread. The paragraph was intended to show that this isn't the only option, however.
async/await is not just about using more threads. It's about using the threads you have more effectively. When operations block, such as waiting on a download or file read, the async/await pattern allows you to use that existing thread for something else. The compiler handles all the magic plumbing underneath, making it much easier to develop with.
See http://msdn.microsoft.com/en-us/magazine/hh456401.aspx for the problem description and the whitepaper at http://www.microsoft.com/en-us/download/details.aspx?id=14058.
Not the code generated by the async and await keyword themselves, no. They create code that runs on your the current thread, assuming it has a synchronization context. If it doesn't then you actually do get threads, but that's using the pattern for no good reason. The await expression, what you write on the right side of the await keyword causes threads to run.
But that thread is often not observable, it may be a device driver thread. Which reports that it is done with a I/O completion port. Pretty common, I/O is always a good reason to use await. If not already forced on you by WinRT, the real reason that async/await got added.
A note about "having a synchronization context". You have one on a thread if the SynchronizationContext.Current property is not null. This is almost only ever the case on the main thread of a gui app. Also the only place where you normally ever worry about having delays not freeze your user interface.
Essentially what it's doing is when you run an async method without calling it with await is this:
Start the method and do as much as possible sychronously.
When necessary, pause the method and put the rest of it into a continuation.
When the async part is completed (is no longer being waited on), schedule the continuation to run on the same thread.
Whatever you want can run on this thread as normal. You can even examine/manipulate the Task returned from the async method.
When the thread becomes available, it will run the rest of your method.
The 'async part' could be file IO, a web request, or pretty much anything, as long as calling code can wait on this task to complete. This includes, but is not limited to, a separate thread. As Reed Copsey pointed out, there are other ways of performing async operations, like interrupts.