So, as everyone knows, frameworks like asp.NET, WPF and WinRT manage one or more threads for you. In asp.NET, the framework pools a set of threads that take requests from a queue and process them. In WPF, the framework manages the UI thread for you, which takes messages from the message pump.
This can be achieved with a simple producer/consumer approach, where the consuming thread executes a while(true) loop, takes messages from a queue and uses a message handler (the user's code) to execute them. Simple enough. You can find a basic implementation here: https://stackoverflow.com/a/5828863/857807
With the introduction of the async/await semantics, you can delegate CPU/IO-intensive work to some other thread, and leave the (for example) UI thread responsive. This means that the UI thread will keep taking messages from the pump.
My question is: starting with the aforementioned basic implementation, how would the consumer implement this? How would you know that the message handler is asynchronously awaiting for another thread to complete and, therefore, take another message from the queue? I'm sure I'm missing something big here.
The key is that when an async method yields in an await, it actually returns to its caller. So, from the perspective of the main loop, the method has completed.
Later on, when the awaitable operation completes, it schedules the remainder of the async method to the captured context. In the cases you mentioned (ASP.NET / WPF / WinRT), the context is a SynchronizationContext. In the UI frameworks (WPF / WinRT / WinForms / etc), that SynchronizationContext is tied to the message queue.
So if you want an async-compatible "main loop", you'd need to implement a custom SynchronizationContext that allows scheduling delegates back to that main loop.
For more information:
My async intro describes how async and await methods return and capture context.
My SynchronizationContext MSDN article describes the relevant portions of that type, and how it's used throughout the .NET framework.
My AsyncEx library has an async-compatible "main loop", including documentation, source, and unit tests.
Related
I have been educating myself on async / await use and I think I understood under-the-hood concept. However, most of Channel 9 tutorials, MSDN articles and Stack overflow answers on async / await use GUI-based applications (Windows Forms application) to demonstrate the power of async / await.
However, I noticed a fundamental difference in async / await use in a UI-thread based application vs. regular ThreadPool thread-based applications (e.g. ASP.NET Web Application, Console Application, etc.).
Since, in UI thread-based application, the UI thread is always available (unless the process is stopped explicitly or by Windows), so the ThreadPool thread responsible for executing the code after "await" in any async method, will guarantee to find the UI thread to post the results back (if any).
However, in a console application or ASP.NET Web application, the main thread (in a console application) or the HTTP request (in an ASP.NET web application) must be waiting (at one point of time) until all async operations are completed. So there should be .Wait() and .Result call somewhere after the Async method call, if there is nothing more to work on.
Is this understanding correct? I am not questioning the benefit of having async for I/O bound or network-bound operations (I understand how it's going to increase application scalability).
Since, in UI thread based application, the UI thread is always available (unless the process is stopped explicitly or by Windows), so the ThreadPool thread responsible for executing the code after "await" in any async method, will guarantee to find the UI thread to post the results back (if any).
This is slightly confused. There's no indication that a ThreadPool thread will be required at all.
It's up to the awaitable implementation to determine where to run the continuation, but normally the current synchronization context is used to work out where to run it:
In a console application, there is no synchronization context, so a thread pool thread is used for the continuation.
In a Windows Forms application, when you're running on the UI thread the synchronization context is one which will execute code on the UI thread... so the continuation executes there (unless you use ConfigureAwait, etc...)
In an ASP.NET application, there's a synchronization context specific to ASP.NET itself.
See Stephen Cleary's MSDN article for more details.
It's not clear what you mean by your later question about having to call Wait or Result in ASP.NET or a console app... in both scenarios it may be required, but equally it may not be. It depends on what you're doing really. Don't forget that even a console app can start its own threads and do all kinds of other things - you can write an HTTP server in a console app, for example...
Why would I decide to choose working directly with System.Threading over BackgroundWorker if the last one abstracts for me the treading managemnet?
I can't see cases where I couldn't use BackgroundWorker to replace System.Threading
BackgroundWorker has been around since .NET 2.0 and was intended to aid in writing code that will run in a background thread and not bog down the UI thread. It originally appeared with Windows Forms, but also works with WPF or any future UI framework that registers a synchronization context. It allows you to report progress and results back to the UI thread without having to deal with InvokeRequired/BeginInvoke as well supports cancellation.
The Task Parallel Library (TPL) was introduced in .NET 4 and is intended to model asynchronous tasks. These tasks are asynchronous and may or may not be run on another thread. Examples of something that doesn't run on another thread is asynchronous IO and tasks that need to run on the UI (while still being asynchronous). This task metaphor also supports futures (or continuations) so that you can chain tasks together with ContinueWith, sometimes using specific synchronization contexts so that you can do things like run a task on a UI thread (to update the UI, for example).
Tasks also support cancellation and multiple tasks can share a cancellation token so a requested cancellation cancels multiple tasks.
One of the differences is a Task doesn't have an inherent method of reporting progress back to the UI. Of course it's possible, but it's not built into the interfaces. Tasks also support cancellation.
If you only have one thing you want to do in the background and you specifically want to communicate back to a UI like report progress, I would recommend BackgroundWorker. Otherwise I generally recommend using Task<T> (or Task if no result is necessary). Task is inherently used in the C# 5 async/await syntax...
I hope you attempt to think about the intention of each approaches.
BackgroundWorker was designed for Windows Forms mainly at the very beginning (though it can be used in WPF as well), and it only offers some functionality of asynchronous operation. Compared it to all classes under System.Threading, you can see BackgroundWorker obviously is built upon them.
With all classes under System.Threading, you can build your own BackgroundWorker and enjoy more functionality and control over your code. The difficulty here is sharp learning curve, and debugging challenges.
So if you think BackgroundWorker is enough, keep using it. If you find something missing, building blocks in System.Threading can be your helpers.
In .NET Framework 4, Microsoft designs another set of classes upon System.Threading, named Task-based Asynchronous Pattern,
http://www.microsoft.com/en-us/download/details.aspx?id=19957
Using it, you can almost forget about BackgroundWorker, as it offers much more functionality and give you enough control, while does not require you to dive into the complexity of working with System.Threading directly.
I have a blog post on the subject.
In short, you should use async Tasks if you possibly can. Thread does provide some additional "knobs" - such as Priority - but usually those knobs are not necessary, and programmers often turn them the wrong way anyway.
For one you cannot set scheduling priority on BackgroundWorker but you can on a Thread.
Thread.Priority Property
Comments that question my answer continue to refer to Task and ThreadPool. The stated question is not about Task nor ThreadPool and neither is my answer.
Please refer to the code sample from the link above. It clearly demonstrates assigning priority prior to starting the thread and control over starting the thread.
Complete code sample:
PriorityTest priorityTest = new PriorityTest();
ThreadStart startDelegate = new ThreadStart(priorityTest.ThreadMethod);
Thread threadOne = new Thread(startDelegate);
threadOne.Name = "ThreadOne";
Thread threadTwo = new Thread(startDelegate);
threadTwo.Name = "ThreadTwo";
threadTwo.Priority = ThreadPriority.BelowNormal;
threadOne.Start();
threadTwo.Start();
// Allow counting for 10 seconds.
Thread.Sleep(10000);
priorityTest.LoopSwitch = false;
I tested this and ThreadTwo starts and finishes on ThreadPriority.BelowNormal. In my test threadOne processes about 10X as threadTwo.
BackGroundWorker has no Priority property. A BackgroundWorker starts with the default priority of Normal. BackgroundWorker thread priority can be changed in DoWork but changing the priority of a thread once the work has started is clearly not the same.
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.
I've created a Windows service based on the ServiceBase class. In this service I created an instance of the NamedPipeClientStream (m_Stream). After connecting this stream I start an asynchronous read using the BeginRead() method:
m_Stream.BeginRead( m_ReadBuffer, 0, 2, ReadAsyncCallback, m_ReadInfo );
In the callback routine ReadAsyncCallback, which indeed gets called, I call EndRead() for the stream (which gives me the number of bytes read, in this case 2). Next, I want to signal the original thread that the read has been completed. For this I use the Dispatcher.Invoke method:
m_Dispatcher.Invoke( new ReadDelegate( this.OnRead ), bytesRead);
(m_Dispatcher was created in the original thread using System.Windows.Threading.Dispatcher.CurrentDispatcher.)
At this point I expected the OnRead method to get called in the original thread, but it doesn't. The Invoke() method doesn't return, it seems to 'hang'.
I hope someone can help me with this. Please let me know if you need more info, I will try to give it to you asap.
Greetings,
Richard
The System.Windows.Threading.Dispatcher requires a correctly configured SynchronizationContext in order for it to work as you normally expect. When in the context of a WPF application the synchronization context is automatically created for you, however in your Windows Service that does not happen and that's why you see the hang.
Also, aside the synchronization context, since I believe the Dispatcher works in a similar way to the Control.Invoke or BackgroundWorker in Windows Forms, your Windows Service main thread must be pumping a message loop in order for you to be able to inject your call into it.
I have written a blog about how the BackgroundWorker class reacts differently according to the context in which its run (Windows Forms, Console or Windows Service), which you may find to be an interesting read since the mechanism used by that class is similar to the WPF Dispatcher.
Inside BackgroundWorker
Finally, for a more in depth dive into how the synchronization contexts work you should read:
It's All About the SynchronizationContext
The thread that called CurrentDispatcher is probably not pumping messages for some reason. The most likely reason is because it does not have any message pumping mechanism. For Invoke to work correctly the target thread must be specially designed to accept delegate injections. This is usually accomplished by having the target thread spin in an infinite loop waiting for messages to appear in a queue. Another thread would then submit a special message requesting the execution of a delegate. This is all setup automatically on the UI thread of Windows Forms or WPF applications. It will not exist in Windows Service application unless you get it going manually.
I would not attempt to use this delegate marshaling technique (or any technique that synchronously injects a delegate into another thread) anyway. The reason is because it will cause that asynchronous IO callback, which is executing on a ThreadPool thread or IO completion port thread, to block until that marshaled delegate completes. You do not want to tie up the IO in this manner.
Instead you should publish the data that is read from the stream into a shared data structure, like a queue or list, and then have your original thread pick it up on a specific interval. If the original thread is expected to wait for data to be read from the stream then you could setup the producer-consumer pattern. This is pretty easy with the BlockingCollection. The original thread will call Take which will block until an item arrives and the IO callback will publish the data by calling Add.
There are other acceptable ways this could be handled, but calling Invoke is probably not one of them.
I can not find any documentation that specifies on which thread WebClient raises its events. I ran some tests and determined the following:
If called from a UI thread (say from an event handler) the event handler will be executed on that thread. As a test, I added an infinite loop after the call to OpenReadAsync. The event handler was never called.
If there is no UI thread, like in a console application, the event handler will be executed on a thread pool thread. In this case, if I wanted to provide some results the rest of the application, I would have to be aware of threading issues.
Is this behaviour documented anywhere? I found nothing.
I have the basically the same question concerning the new async features of C# - eventually, the asynchronous code will have to be executed. Will that also spawn a thread pool thread when there is no UI thread? Will that, in turn, require thread safe code?
I feel that I am missing something here - I can only find very little information about this, but this seems important to me.
For WebClient, I haven't found it documented either, but have seen the same behaviour as you. Essentially this can be described as "if there's an active synchronization context when the call is started, it's used - otherwise the thread pool is used."
For the async behaviour in C# 5, it depends on the implementation of whatever you're awaiting... but I believe the awaiter for Task<T> will use TaskScheduler.Current to schedule a continuation - which means you'll see the same sort of behaviour. (It's not necessarily just a UI thread which sets a task scheduler, but that's the most obvious example.)
When thread pool threads are used, it should still be thread-safe - the method is only executing in a single thread at a time, and I believe the Task Parallel Library performs all the required memory barriers.
If you're interested in how async hangs together behind the scenes, you might want to read my Eduasync blog series.
The WebClient Class implements the Event-based Asynchronous Pattern. The pattern is fully described in the Framework Design Guidelines, but MSDN also provides a few hints how it is implemented:
Implementors of the pattern use the AsyncOperationManager to create an AsyncOperation for each asynchronous operation and raise events using the AsyncOperation.Post Method. The Post Method executes the passed callback on the SynchronizationContext that was current at the time when the AsyncOperation was created.
The default SynchronizationContext in a WinForms or WPF application is the UI thread, or null in a Console application. The WebClient Class apparently chooses to raise the events in a ThreadPool thread in the latter case, but this is an implementation detail.