SO I've been doing a ton of reading lately about the net Async CTP and one thing that keeps coming up are sentences like these: "Asynchrony is not about starting new threads, its about multiplexing work", and "Asynchrony without multithreading is the same idea [as cooperative multitasking]. You do a task for a while, and when it yields control, you do another task for a while on that thread".
I'm trying to understand whether remarks like this are purely (well, mostly) esoteric and academic or whether there is some language construct I'm overlooking that allows the tasks I start via "await" to magically run on the UI thread.
In his blog, Eric Lippert gives this example as a demonstration of how you can have Asyncrhony without multithreading:
async void FrobAll()
{
for(int i = 0; i < 100; ++i)
{
await FrobAsync(i); // somehow get a started task for doing a Frob(i) operation on this thread
}
}
Now, it's the comment that intrigues me here: "...get a started task for doing a Frob(i) operation on this thread".
Just how is this possible? Is this a mostly theoretical remark? The only cases I can see so far where a task appears to not need a separate thread (well, you can't know for sure unless you examine the code) would be something like Task.Delay(), which one can await on without starting another thread. But I consider this a special case, since I didn't write the code for that.
For the average user who wants to offload some of their own long running code from the GUI thread, aren't we talking primarily about doing something like Task.Run to get our work offloaded, and isn't that going to start it in another thread? If so, why all this arm waiving about not confusing asynchorny with multithreading?
Please see my intro to async/await.
In the case of CPU work, you do have to use something like Task.Run to execute it in another thread. However, there's a whole lot of work which is not CPU work (network requests, file system requests, timers, ...), and each of those can be wrapped in a Task without using a thread.
Remember, at the driver level, everything is asynchronous. The synchronous Win32 APIs are just convenience wrappers.
Not 100% sure, but from the article it sounds like what's going on is that it allows windows messages (resize events, mouse clicks, etc) to be interleaved between the calls to FrobAsync. Roughly analogous to:
void FrobAll()
{
for(int i = 0; i < 100; ++i)
{
FrobAsync(i); // somehow get a started task for doing a Frob(i) operation on this thread
System.Windows.Forms.Application.DoEvents();
}
}
or maybe more accurately:
void FrobAll()
{
SynchronizationContext.Current.Post(QueueFrob, 0);
}
void QueueFrob(Object state) {
var i = (int)state;
FrobAsync(i);
if (i == 99) return;
SynchronizationContext.Current.Post(QueueFrob, i+1);
}
Without the nasty call to DoEvents between each iteration. The reason that this occurs is because the call to await sends a Windows message that enqueues the FrobAsync call, allowing any windows messages that occurred between Frobbings to be executed before the next Frobbing begins.
async/await is simply about asynchronous. From the caller side, it doesn't matter if multiple threads are being used or not--simply that it does something asynchronous. IO completion ports, for example, are asychronous but doesn't do any multi-threading (completion of the operation occurs on a background thread; but the "work" wasn't done on that thread).
From the await keyword, "multi-threaded" is meaningless. What the async operation does is an implementation detail.
In the sense of Eric's example, that method could have been implemented as follows:
return Task.Factory.StartNew(SomeMethod,
TaskScheduler.FromCurrentSynchronizationContext());
Which really means queue a call to SomeMethod on the current thread when it's done all the currently queued work. That's asynchronous to the caller of FrobAsync in that FrobAsync returns likely before SomeMethod is executed.
Now, FrobAsync could have been implemented to use multithreading, in which case it could have been written like this:
return Task.Factory.StartNew(SomeMethod);
which would, if the default TaskScheduler was not changed, use the thread pool. But, from the caller's perspective, nothing has changed--you still await the method.
From the perspective of multi-threading, this is what you should be looking at. Using Task.Start, Task.Run, or Task.Factory.StartNew.
Related
I have a similair question to Running async methods in parallel in that I wish to run a number of functions from a list of functions in parallel.
I have noted in a number of comments online it is mentioned that if you have another await in your methods, Task.WhenAll() will not help as Async methods are not parallel.
I then went ahead and created a thread for each using function call with the below (the number of parallel functions will be small typically 1 to 5):
public interface IChannel
{
Task SendAsync(IMessage message);
}
public class SendingChannelCollection
{
protected List<IChannel> _channels = new List<IChannel>();
/* snip methods to add channels to list etc */
public async Task SendAsync(IMessage message)
{
var tasks = SendAll(message);
await Task.WhenAll(tasks.AsParallel().Select(async task => await task));
}
private IEnumerable<Task> SendAll(IMessage message)
{
foreach (var channel in _channels)
yield return channel.SendAsync(message, qos);
}
}
I would like to double check I am not doing anything horrendous with code smells or bugs as i get to grips with what I have patched together from what i have found online. Many thanks in advance.
Let's compare the behaviour of your line:
await Task.WhenAll(tasks.AsParallel().Select(async task => await task));
in contrast with:
await Task.WhenAll(tasks);
What are you delegating to PLINQ in the first case? Only the await operation, which does basically nothing - it invokes the async/await machinery to wait for one task. So you're setting up a PLINQ query that does all the heavy work of partitioning and merging the results of an operation that amounts to "do nothing until this task completes". I doubt that is what you want.
If you have another await in your methods, Task.WhenAll() will not help as Async methods are not parallel.
I couldn't find that in any of the answers to the linked questions, except for one comment under the question itself. I'd say that it's probably a misconception, stemming from the fact that async/await doesn't magically turn your code into concurrent code. But, assuming you're in an environment without a custom SynchronizationContext (so not an ASP or WPF app), continuations to async functions will be scheduled on the thread pool and possibly run in parallel. I'll delegate you to this answer to shed some light on that. That basically means that if your SendAsync looks something like this:
Task SendAsync(IMessage message)
{
// Synchronous initialization code.
await something;
// Continuation code.
}
Then:
The first part before await runs synchronously. If this part is heavyweight, you should introduce parallelism in SendAll so that the initialization code is run in parallel.
await works as usual, waiting for work to complete without using up any threads.
The continuation code will be scheduled on the thread pool, so if a few awaits finish up at the same time their continuations might be run in parallel if there's enough threads in the thread pool.
All of the above is assuming that await something actually awaits asynchronously. If there's a chance that await something completes synchronously, then the continuation code will also run synchronously.
Now there is a catch. In the question you linked one of the answers states:
Task.WhenAll() has a tendency to become unperformant with large scale/amount of tasks firing simultaneously - without moderation/throttling.
Now I don't know if that's true, since I weren't able to find any other source claiming that. I guess it's possible and in that case it might actually be beneficial to invoke PLINQ to deal with partitioning and throttling for you. However, you said you typically handle 1-5 functions, so you shouldn't worry about this.
So to summarize, parallelism is hard and the correct approach depends on how exactly your SendAsync method looks like. If it has heavyweight initialization code and that's what you want to parallelise, you should run all the calls to SendAsync in parallel. Otherwise, async/await will be implicitly using the thread pool anyway, so your call to PLINQ is redundant.
I've searched the web and seen a lot of questions regarding Task.Run vs await async, but there is this specific usage scenario where I don't not really understand the difference. Scenario is quite simple i believe.
await Task.Run(() => LongProcess());
vs
await LongProcess());
where LongProcess is a async method with a few asynchronous calls in it like calling db with await ExecuteReaderAsync() for instance.
Question:
Is there any difference between the two in this scenario? Any help or input appreciated, thanks!
Task.Run may post the operation to be processed at a different thread. That's the only difference.
This may be of use - for example, if LongProcess isn't truly asynchronous, it will make the caller return faster. But for a truly asynchronous method, there's no point in using Task.Run, and it may result in unnecessary waste.
Be careful, though, because the behaviour of Task.Run will change based on overload resolution. In your example, the Func<Task> overload will be chosen, which will (correctly) wait for LongProcess to finish. However, if a non-task-returning delegate was used, Task.Run will only wait for execution up to the first await (note that this is how TaskFactory.StartNew will always behave, so don't use that).
Quite often people think that async-await is done by several threads. In fact it is all done by one thread.
See the addition below about this one thread statement
The thing that helped me a lot to understand async-await is this interview with Eric Lippert about async-await. Somewhere in the middle he compares async await with a cook who has to wait for some water to boil. Instead of doing nothing, he looks around to see if there is still something else to do like slicing the onions. If that is finished, and the water still doesn't boil he checks if there is something else to do, and so forth until he has nothing to do but wait. In that case he returns to the first thing he waited for.
If your procedure calls an awaitable function, we are certain that somewhere in this awaitable function there is a call to an awaitable function, otherwise the function wouldn't be awaitable. In fact, your compiler will warn you if you forget to await somewhere in your awaitable function.
If your awaitable function calls the other awaitable function, then the thread enters this other function and starts doing the things in this function and goes deeper into other functions until he meets an await.
Instead of waiting for the results, the thread goes up in his call stack to see if there are other pieces of code he can process until he sees an await. Go up again in the call stack, process until await, etc. Once everyone is awaiting the thread looks for the bottom await and continues once that is finished.
This has the advantage, that if the caller of your awaitable function does not need the result of your function, but can do other things before the result is needed, these other things can be done by the thread instead of waiting inside your function.
A call without waiting immediately for the result would look like this:
private async Task MyFunction()
{
Task<ReturnType>taskA = SomeFunctionAsync(...)
// I don't need the result yet, I can do something else
DoSomethingElse();
// now I need the result of SomeFunctionAsync, await for it:
ReturnType result = await TaskA;
// now you can use object result
}
Note that in this scenario everything is done by one thread. As long as your thread has something to do he will be busy.
Addition. It is not true that only one thread is involved. Any thread who has nothing to do might continue processing your code after an await. If you check the thread id, you can see that this id can be changed after the await. The continuing thread has the same context as the original thread, so you can act as if it was the original thread. No need to check for InvokeRequired, no need to use mutexes or critical sections. For your code this is as if there is one thread involved.
The link to the article in the end of this answer explains a bit more about thread context
You'll see awaitable functions mainly where some other process has to do things, while your thread just has to wait idly until the other thing is finished. Examples are sending data over the internet, saving a file, communicating with a database etc.
However, sometimes some heavy calculations has to be done, and you want your thread to be free to do something else, like respond to user input. In that case you can start an awaitable action as if you called an async function.
Task<ResultType> LetSomeoneDoHeavyCalculations(...)
{
DoSomePreparations()
// start a different thread that does the heavy calculations:
var myTask = Task.Run( () => DoHeavyCalculations(...))
// now you are free to do other things
DoSomethingElse();
// once you need the result of the HeavyCalculations await for it
var myResult = await myTask;
// use myResult
...
}
Now a different thread is doing the heavy calculations while your thread is free to do other things. Once it starts awaiting your caller can do things until he starts awaiting. Effectively your thread will be fairly free to react on user input. However, this will only be the case if everyone is awaiting. While your thread is busy doing things your thread can't react on user input. Therefore always make sure that if you think your UI thread has to do some busy processing that takes some time use Task.Run and let another thread do it
Another article that helped me: Async-Await by the brilliant explainer Stephen Cleary
This answer deals with the specific case of awaiting an async method in the event handler of a GUI application. In this case the first approach has a significant advantage over the second. Before explaining why, lets rewrite the two approaches in a way that reflects clearly the context of this answer. What follows is only relevant for event handlers of GUI applications.
private async void Button1_Click(object sender, EventArgs args)
{
await Task.Run(async () => await LongProcessAsync());
}
vs
private async void Button1_Click(object sender, EventArgs args)
{
await LongProcessAsync();
}
I added the suffix Async in the method's name, to comply with the guidlines. I also made async the anonymous delegate, just for readability reasons. The overhead of creating a state machine is minuscule, and is dwarfed by the value of communicating clearly that this Task.Run returns a promise-style Task, not an old-school delegate Task intended for background processing of CPU-bound workloads.
The advantage of the first approach is that guarantees that the UI will remain responsive. The second approach offers no such guarantee. As long as you are using the build-in async APIs of the .NET platform, the probability of the UI being blocked by the second approach is pretty small. After all, these APIs are implemented by experts¹. By the moment you start awaiting your own async methods, all guarantees are off. Unless of course your first name is Stephen, and your surname is Toub or Cleary. If that's not the case, it is quite possible that sooner or later you'll write code like this:
public static async Task LongProcessAsync()
{
TeenyWeenyInitialization(); // Synchronous
await SomeBuildInAsyncMethod().ConfigureAwait(false); // Asynchronous
CalculateAndSave(); // Synchronous
}
The problem obviously is with the method TeenyWeenyInitialization(). This method is synchronous, and comes before the first await inside the body of the async method, so it won't be awaited. It will run synchronously every time you call the LongProcessAsync(). So if you follow the second approach (without Task.Run), the TeenyWeenyInitialization() will run on the UI thread.
How bad this can be? The initialization is teeny-weeny after all! Just a quick trip to the database to get a value, read the first line of a small text file, get a value from the registry. It's all over in a couple of milliseconds. At the time you wrote the program. In your PC. Before moving the data folder in a shared drive. Before the amount of data in the database became huge.
But you may get lucky and the TeenyWeenyInitialization() remains fast forever, what about the second synchronous method, the CalculateAndSave()? This one comes after an await that is configured to not capture the context, so it runs on a thread-pool thread. It should never run on the UI thread, right? Wrong. It depends to the Task returned by SomeBuildInAsyncMethod(). If the Task is completed, a thread switch will not occur, and the CalculateAndSave() will run on the same thread that called the method. If you follow the second approach, this will be the UI thread. You may never experience a case where the SomeBuildInAsyncMethod() returned a completed Task in your development environment, but the production environment may be different in ways difficult to predict.
Having an application that performs badly is unpleasant. Having an application that performs badly and freezes the UI is even worse. Do you really want to risk it? If you don't, please use always Task.Run(async inside your event handlers. Especially when awaiting methods you have coded yourself!
¹ Disclaimer, some built-in async APIs are not properly implemented.
Important: The Task.Run runs the supplied asynchronous delegate on a ThreadPool thread, so it's required that the LongProcessAsync has no affinity to the UI thread. If it involves interaction with UI controls, then the Task.Runis not an option. Thanks to #Zmaster for pointing out this important subtlety in the comments.
I have the following code that connects to a SignalR Hub
private static async Task StartListening()
{
try
{
var hubConnection = new HubConnection("http://localhost:8080/");
IHubProxy hubProxy = hubConnection.CreateHubProxy("Broadcaster");
hubProxy.On<EventData>("notifyCardAccessEvent", eventData =>
{
Log.Info(string.Format("Incoming data: {0} {1}", eventData.Id, eventData.DateTime));
});
ServicePointManager.DefaultConnectionLimit = 10;
await hubConnection.Start();
Log.Info("Connected");
}
catch (Exception ex)
{
Log.Error(ex);
}
}
In my Form_Load method, I have this
StartListening();
However, Resharper prompts me to "consider applying the 'await' operator to the result of the call"
So I did this:
Log.Info("Connecting to SignalR hub...");
StartListening().Wait();
Log.Info("Connected!");
However, this causes my UI thread to hang and Connected! is never printed to the log file.
So my question is, when should I use Wait()? What are the instances and scenarios that I should use Wait(), and when should I not use Wait()?
await is not Wait. It is unclear what the code is that is calling StartListening(), but one option is to await it, as suggested:
await StartListening();
However, in some other cases it may be better to do nothing at all:
StartListening(); // drop the Task on the floor
or perhaps use ContinueWith for a manual continuation. Since the StartListening method catches any exceptions, there isn't anything wrong with just ignoring the returned Task - so what you had already. I would suggest calling it StartListeningAsync, though.
The reason for the deadlock is that if you use Wait, your UI thread blocks waiting on an asynchronous method to complete, but that asynchronous method is capturing the sync-context, which means in order to process each continuation it tries to get onto the UI thread - which is blocked... on it.
#MarcGravell has the correct answer; I'm just going to answer this other question:
So my question is, when should I use Wait()? What are the instances and scenarios that I should use Wait(), and when should I not use Wait()?
The confusion is coming from the fact that the Task type is used for two almost completely different things.
Task was originally introduced in .NET 4.0 as part of the Task Parallel Library. Normally, you would use Parallel LINQ or the Parallel class for parallel processing (which used the Task type underneath). However, in advanced scenarios, you could use the Task type directly. Task.Wait was used to wait for those independent tasks to complete.
When async/await were introduced in .NET 4.5, the existing Task type was almost good enough to be used as an abstract "future". So instead of inventing some new "future" type, they just slightly extended Task to work as a future.
This brings us to today, where Task can be used as either:
An item of work in a parallel computation.
An asynchronous future.
(There's a tiny bit of crossover: you can treat parallel work as asynchronous, and in rare situations like Console Main methods you do need to block on asynchronous tasks; but ignore those for the moment.)
This means that the API for Task is split along those lines. Members such as Start, Wait, Result, and ContinueWith belong pretty firmly on the parallel side. In the asynchronous world, await is more appropriate.
I have a small table at the bottom of my async intro that has some new (asynchronous) equivalents for the old (parallel) ways of doing things.
You seem to misunderstand the message from Resharper. Instead of applying the await operator, you called the Task.Wait() Method. They may seem similar, but they're working completely different.
This nice answer will provide more information about the differences: https://stackoverflow.com/a/13140963/3465395
I am storing the state of my data model. I clone the data model and then want to have it written to "disk" asynchronously.
Should I be using Task.Run() which runs it on a background thread?
Or should I just make it an async function and not await on it? (this will make it run on the UI thread)
Similar stuff to this, but my question is a bit different:
async Task.Run with MVVM
And what is the criteria to decide which to choose?
Thanks!
You should use Task.Run for CPU-based work that you want to run on a thread pool thread.
In your situation, you want to do I/O based work without blocking the UI, so Task.Run won't get you anything (unless you don't have asynchronous I/O APIs available).
As a side note, you definitely do want to await this work. This makes error handling much cleaner.
So, something like this should suffice:
async void buttonSaveClick(..)
{
buttonSave.Enabled = false;
try
{
await myModel.Clone().SaveAsync();
}
catch (Exception ex)
{
// Display error.
}
buttonSave.Enabled = true;
}
I don't think it matters. As far as I know, both methods get dispatched to a thread in the thread pool.
Using async will make the async method run on a background thread and continue on the thread that started it when the async method is finished. You can imagine the compiler seeing the await keyword, put the awaited method in a background thread and wiring up events to notice when the asynch method is finished. Therefore this might be the better choice if you want to show a UI change because of the successful save, and because this is lesser code of course.
Task.Run() would be nicer when you for any reason don't want to put the code in an async method, for example because you want the calling method itself not be async. Also, there's lesser event marshaling involved, but I heavily doubt that there's any performance difference at all.
I don't see the different between C#'s (and VB's) new async features, and .NET 4.0's Task Parallel Library. Take, for example, Eric Lippert's code from here:
async void ArchiveDocuments(List<Url> urls) {
Task archive = null;
for(int i = 0; i < urls.Count; ++i) {
var document = await FetchAsync(urls[i]);
if (archive != null)
await archive;
archive = ArchiveAsync(document);
}
}
It seems that the await keyword is serving two different purposes. The first occurrence (FetchAsync) seems to mean, "If this value is used later in the method and its task isn't finished, wait until it completes before continuing." The second instance (archive) seems to mean, "If this task is not yet finished, wait right now until it completes." If I'm wrong, please correct me.
Couldn't it just as easily be written like this?
void ArchiveDocuments(List<Url> urls) {
for(int i = 0; i < urls.Count; ++i) {
var document = FetchAsync(urls[i]); // removed await
if (archive != null)
archive.Wait(); // changed to .Wait()
archive = ArchiveAsync(document.Result); // added .Result
}
}
I've replaced the first await with a Task.Result where the value is actually needed, and the second await with Task.Wait(), where the wait is actually occurring. The functionality is (1) already implemented, and (2) much closer semantically to what is actually happening in the code.
I do realize that an async method is rewritten as a state machine, similar to iterators, but I also don't see what benefits that brings. Any code that requires another thread to operate (such as downloading) will still require another thread, and any code that doesn't (such as reading from a file) could still utilize the TPL to work with only a single thread.
I'm obviously missing something huge here; can anybody help me understand this a little better?
I think the misunderstanding arises here:
It seems that the await keyword is serving two different purposes. The first occurrence (FetchAsync) seems to mean, "If this value is used later in the method and its task isn't finished, wait until it completes before continuing." The second instance (archive) seems to mean, "If this task is not yet finished, wait right now until it completes." If I'm wrong, please correct me.
This is actually completely incorrect. Both of these have the same meaning.
In your first case:
var document = await FetchAsync(urls[i]);
What happens here, is that the runtime says "Start calling FetchAsync, then return the current execution point to the thread calling this method." There is no "waiting" here - instead, execution returns to the calling synchronization context, and things keep churning. At some point in the future, FetchAsync's Task will complete, and at that point, this code will resume on the calling thread's synchronization context, and the next statement (assigning the document variable) will occur.
Execution will then continue until the second await call - at which time, the same thing will happen - if the Task<T> (archive) isn't complete, execution will be released to the calling context - otherwise, the archive will be set.
In the second case, things are very different - here, you're explicitly blocking, which means that the calling synchronization context will never get a chance to execute any code until your entire method completes. Granted, there is still asynchrony, but the asynchrony is completely contained within this block of code - no code outside of this pasted code will happen on this thread until all of your code completes.
Anders boiled it down to a very succinct answer in the Channel 9 Live interview he did. I highly recommend it
The new Async and await keywords allow you to orchestrate concurrency in your applications. They don't actually introduce any concurrency in to your application.
TPL and more specifically Task is one way you can use to actually perform operations concurrently. The new async and await keyword allow you to compose these concurrent operations in a "synchronous" or "linear" fashion.
So you can still write a linear flow of control in your programs while the actual computing may or may not happen concurrently. When computation does happen concurrently, await and async allow you to compose these operations.
There is a huge difference:
Wait() blocks, await does not block. If you run the async version of ArchiveDocuments() on your GUI thread, the GUI will stay responsive while the fetching and archiving operations are running.
If you use the TPL version with Wait(), your GUI will be blocked.
Note that async manages to do this without introducing any threads - at the point of the await, control is simply returned to the message loop. Once the task being waited for has completed, the remainder of the method (continuation) is enqueued on the message loop and the GUI thread will continue running ArchiveDocuments where it left off.
The ability to turn the program flow of control into a state machine is what makes these new keywords intresting. Think of it as yielding control, rather than values.
Check out this Channel 9 video of Anders talking about the new feature.
The problem here is that the signature of ArchiveDocuments is misleading. It has an explicit return of void but really the return is Task. To me void implies synchronous as there is no way to "wait" for it to finish. Consider the alternate signature of the function.
async Task ArchiveDocuments(List<Url> urls) {
...
}
To me when it's written this way the difference is much more obvious. The ArchiveDocuments function is not one that completes synchronously but will finish later.
The await keyword does not introduce concurrency. It is like the yield keyword, it tells the compiler to restructure your code into lambda controlled by a state machine.
To see what await code would look like without 'await' see this excellent link: http://blogs.msdn.com/b/windowsappdev/archive/2012/04/24/diving-deep-with-winrt-and-await.aspx
The call to FetchAsync() will still block until it completes (unless a statement within calls await?) The key is that control is returned to the caller (because the ArchiveDocuments method itself is declared as async). So the caller can happily continue processing UI logic, respond to events, etc.
When FetchAsync() completes, it interrupts the caller to finish the loop. It hits ArchiveAsync() and blocks, but ArchiveAsync() probably just creates a new task, starts it, and returns the task. This allows the second loop to begin, while the task is processing.
The second loop hits FetchAsync() and blocks, returning control to the caller. When FetchAsync() completes, it again interrupts the caller to continue processing. It then hits await archive, which returns control to the caller until the Task created in loop 1 completes. Once that task is complete, the caller is again interrupted, and the second loop calls ArchiveAsync(), which gets a started task and begins loop 3, repeat ad nauseum.
The key is returning control to the caller while the heavy lifters are executing.