I was reading about asynchronous function calls on Asynchronous Programming with Async and Await.
At the first example, they do this, which I get:
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
// You can do work here that doesn't rely on the string from GetStringAsync.
DoIndependentWork();
string urlContents = await getStringTask;
But then they explain that if there's not any work to be done in the mean time, you can just do it like this:
string urlContents = await client.GetStringAsync();
From what I understand, the await keyword will suspend the code flow until the function returns. So how is this different from the synchronous call below?
string urlContents = client.GetString();
Calling await client.GetStringAsync() yields the execution to the calling method, which means it won't wait for the method to finish executing, and thus won't block the thread. Once it's done executing in the background, the method will continue from where it stopped.
If you just call client.GetString(), the thread's execution won't continue until this method finished executing, which will block the thread and may cause the UI to become unresponsive.
Example:
public void MainFunc()
{
InnerFunc();
Console.WriteLine("InnerFunc finished");
}
public async Task InnerFunc()
{
// This causes InnerFunc to return execution to MainFunc,
// which will display "InnerFunc finished" immediately.
string urlContents = await client.GetStringAsync();
// Do stuff with urlContents
}
public void InnerFunc()
{
// "InnerFunc finished" will only be displayed when InnerFunc returns,
// which may take a while since GetString is a costly call.
string urlContents = client.GetString();
// Do stuff with urlContents
}
From what I understand, the await keyword will suspend the code flow until the function returns
Well, Yes and No.
Yes, because code flow does stop in a sense.
No, because the thread executing this code flow does not block. (The synchronous call client.GetString() will block the thread).
In fact, it will return to its calling method. To understand what it means by return to its calling method, you can read about another C# compiler magic - the yield return statement.
Iterator blocks with yield return will break the method into a state machine - where code after the yield return statement will execute only after MoveNext() is called on the enumerator. (See this and this).
Now, async/await mechanism is also based on similar state machine (however, its much more complicated than the yield return state machine).
To simplify matters, lets consider a simple async method:
public async Task MyMethodAsync()
{
// code block 1 - code before await
// await stateement
var r = await SomeAwaitableMethodAsync();
// code block 2 - code after await
}
When you mark a method with async identifier you tell the compiler to break the method into a state machine and that you are going to await inside this method.
Lets say code is running on a thread Thread1 and your code calls this MyMethodAsync(). Then code block 1 will synchronously run on the same thread.
SomeAwaitableMethodAsync() will also be called synchronously - but lets say that method starts a new asynchronous operation and returns a Task.
This is when await comes into picture. It will return the code flow back to its caller and the thread Thread1 is free to run callers code. What happens then in calling method depends on whether calling method awaits on MyMethodAsync() or does something else - but important thing is Thread1 is not blocked.
Now rest of await's magic - When the Task returned by SomeAwaitableMethodAsync() eventually completes, the code block 2 is Scheduled to run.
async/await is built on the Task parallel library - so, this Scheduling is done over TPL.
Now the thing is that this code block 2 may not be scheduled over the same thread Thread1 unless it had an active SynchronizationContext with thread affinity (like WPF/WinForms UI thread). await is SynchronizationContext aware, so, code block 2 is scheduled over same SynchronizationContext, if any, when the MyMethodAsync() was called. If there was no active SynchronizationContext, then with all possibility, code block 2 will run over some different thread.
Lastly, I will say that since async/await is based on state machine created by compiler, like yield return, it shares some of the shortcomings - for example, you cannot await inside a finally block.
I hope this clears your doubts.
Related
When await is encountered, control goes back to caller, while the awaited task runs (makes/waits for network request/response) in background. I know that awaiting task will not need thread when it is awaiting for network response as it is not really running anything but just waiting.
I want to ask - suppose in the awaited function, there is some synchronous code like Console.WriteLine, then because control has gone back to the caller, who executes the console.writeline?
Assume button click event does await Fn1();.
Example 1 :
async Task<string> fn1() {
string result = await NetworkCallAsync('http......');
return result;
}
In above example upon encountering await Fn1(), control goes back to the UI thread, while the network call is made. I understand this. When network call completes, the Ui thread will execute the rest of the code. That is - fetch the result and return.
Example 2:
async Task<string> fn1() {
Console.WriteLine("hello"); //or any other synchronous code like Thread.Sleep(10);
string result = await NetworkCallAsync('http......');
return result;
}
In above code, when the button click encounters the await Fn1() and has returned control to the UI thread, then who executes the Console.WriteLine (or Thread.Sleep(10)) as shown in above example)?
A task does not necessarily need any thread to execute. A task may represent an IO-operation, i.e. disk or network access. If so the task can use the asynchronous features in the OS to avoid using any thread at all while waiting.
If you are starting a task yourself you can specify a taskScheduler that determines what thread to use. Typically either the OS thread or an arbitrary threadpool thread.
It is also possible for tasks to complete synchronously, either because the result is already available, or because the method need to fulfill an API, and using real async IO is to much work.
As the user of a task you should in general not need to care how the task was run, just that it has completed.
The Console.WriteLine("hello"); will be invoked on the same thread where the Fn1() is invoked. The Fn1() will not return a Task<string> before executing all code that comes before the first await inside the Fn1. The Console.WriteLine("hello"); line is located before the first await, so it will run synchronously on the calling thread.
So I have this WrapperFunction that tries to make a FunctionReturningVoid to be called asynchronously:
public async Task WrapperFunction()
{
this.FunctionReturningVoid("aParameter");
}
This is the function that returns nothing. In some parts of the code (not detailed here) it is called SYNChronously but in the CallerFunction() we want it to be run ASYNChronously.
public void FunctionReturningVoid(string myString)
{
Console.Write(myString);
}
This is the function that has the async implemented and needs to have WrapperFunction do its things without blocking otherStuff().
public async Task CallerFunction()
{
await WrapperFunction():
int regular = otherStuff();
...
}
The IDE is warning me that WrapperFunction is not using await:
This async method lacks 'await' operators and will run synchronously.
Consider using the 'await' operator to await non-blocking API calls,
or 'await Task.Run(...)' to do CPU-bound work on a background thread.
Question: How to use async without using await in WrapperFunction? If I use await it tells me that cannot await void.
It's important to distinguish asynchronous from parallel.
Asynchronous means not blocking the current thread while you're waiting for something to happen. This lets the current thread go do something else while waiting.
Parallel means doing more than one thing at the same time. This requires separate threads for each task.
You cannot call FunctionReturningVoid asynchronously because it is not an asynchronous method. In your example, Console.WriteLine() is written in a way that will block the thread until it completes. You can't change that. But I understand that's just your example for this question. If your actual method is doing some kind of I/O operation, like a network request or writing a file, you could rewrite it to use asynchronous methods. But if it's doing CPU-heavy work, or you just can't rewrite it, then you're stuck with it being synchronous - it will block the current thread while it runs.
However, you can run FunctionReturningVoid in parallel (on another thread) and wait for it asynchronously (so it doesn't block the current thread). This would be wise if this is a desktop application - you don't want to lock up your UI while it runs.
To do that, you can use Task.Run, which will start running code on another thread and return a Task that you can use to know when it completes. That means your WrapperFunction would look like this:
public Task WrapperFunction()
{
return Task.Run(() => this.FunctionReturningVoid("aParameter"));
}
Side point: Notice I removed the async keyword. It's not necessary since you can just pass the Task to the calling method. There is more information about this here.
Microsoft has some well-written articles about Asynchronous programming with async and await that are worth the read.
What's the difference between starting and awaiting? Code below taken from Stephen Cleary's blog (including comments)
public async Task DoOperationsConcurrentlyAsync()
{
Task[] tasks = new Task[3];
tasks[0] = DoOperation0Async();
tasks[1] = DoOperation1Async();
tasks[2] = DoOperation2Async();
// At this point, all three tasks are running at the same time.
// Now, we await them all.
await Task.WhenAll(tasks);
}
I thought that the tasks begin running when you await them ... but the comments in the code seem to imply otherwise.
Also, how can the tasks be running after I just attributed them to an array of type Task. Isn't that just an attribution, by nature not involving action?
A Task returns "hot" (i.e. already started). await asynchronously waits for the Task to complete.
In your example, where you actually do the await will affect whether the tasks are ran one after the other, or all of them at the same time:
await DoOperation0Async(); // start DoOperation0Async, wait for completion, then move on
await DoOperation1Async(); // start DoOperation1Async, wait for completion, then move on
await DoOperation2Async(); // start DoOperation2Async, wait for completion, then move on
As opposed to:
tasks[0] = DoOperation0Async(); // start DoOperation0Async, move on without waiting for completion
tasks[1] = DoOperation1Async(); // start DoOperation1Async, move on without waiting for completion
tasks[2] = DoOperation2Async(); // start DoOperation2Async, move on without waiting for completion
await Task.WhenAll(tasks); // wait for all of them to complete
Update
"doesn't await make an async operation... behave like sync, in this example (and not only)? Because we can't (!) run anything else in parallel with DoOperation0Async() in the first case. By comparison, in the 2nd case DoOperation0Async() and DoOperation1Async() run in parallel (e.g. concurrency,the main benefits of async?)"
This is a big subject and a question worth being asked as it's own thread on SO as it deviates from the original question of the difference between starting and awaiting tasks - therefore I'll keep this answer short, while referring you to other answers where appropriate.
No, awaiting an async operation does not make it behave like sync; what these keywords do is enabling developers to write asynchronous code that resembles a synchronous workflow (see this answer by Eric Lippert for more).
Calling await DoOperation0Async() will not block the thread executing this code flow, whereas a synchronous version of DoOperation0 (or something like DoOperation0Async.Result) will block the thread until the operation is complete.
Think about this in a web context. Let's say a request arrives in a server application. As part of producing a response to that request, you need to do a long-running operation (e.g. query an external API to get some value needed to produce your response). If the execution of this long-running operation was synchronous, the thread executing your request would block as it would have to wait for the long-running operation to complete. On the other hand, if the execution of this long-running operation was asynchronous, the request thread could be freed up so it could do other things (like service other requests) while the long-running operation was still running. Then, when the long-running operation would eventually complete, the request thread (or possibly another thread from the thread pool) could pick up from where it left off (as the long-running operation would be complete and it's result would now be available) and do whatever work was left to produce the response.
The server application example also addresses the second part of your question about the main benefits of async - async/await is all about freeing up threads.
Isn't that just an attribution, by nature not involving action?
By calling the async method you execute the code within. Usually down the chain one method will create a Task and return it either by using return or by awaiting.
Starting a Task
You can start a Task by using Task.Run(...). This schedules some work on the Task Thread Pool.
Awaiting a Task
To get a Task you usually call some (async) Method that returns a Task. An async method behaves like a regular method until you await (or use Task.Run() ). Note that if you await down a chain of methods and the "final" method only does a Thread.Sleep() or synchronous operation - then you will block the initial calling thread, because no method ever used the Task's Thread Pool.
You can do some actual asynchronous operation in many ways:
using Task.Run
using Task.Delay
using Task.Yield
call a library that offers asynchronous operations
These are the ones that come to my mind, there are probably more.
By example
Let's assume that Thread ID 1 is the main thread where you are calling MethodA() from. Thread IDs 5 and up are Threads to run Tasks on (System.Threading.Tasks provides a default Scheduler for that).
public async Task MethodA()
{
// Thread ID 1, 0s passed total
var a = MethodB(); // takes 1s
// Thread ID 1, 1s passed total
await Task.WhenAll(a); // takes 2s
// Thread ID 5, 3s passed total
// When the method returns, the SynchronizationContext
// can change the Thread - see below
}
public async Task MethodB()
{
// Thread ID 1, 0s passed total
Thread.Sleep(1000); // simulate blocking operation for 1s
// Thread ID 1, 1s passed total
// the await makes MethodB return a Task to MethodA
// this task is run on the Task ThreadPool
await Task.Delay(2000); // simulate async call for 2s
// Thread ID 2 (Task's pool Thread), 3s passed total
}
We can see that MethodA was blocked on the MethodB until we hit an await statement.
Await, SynchronizationContext, and Console Apps
You should be aware of one feature of Tasks. They make sure to invoke back to a SynchronizationContext if one is present (basically non-console apps). You can easily run into a deadlock when using .Result or .Wait() on a Task if the called code does not take measures. See https://blogs.msdn.microsoft.com/pfxteam/2012/01/20/await-synchronizationcontext-and-console-apps/
async/await as syntactic sugar
await basically just schedules following code to run after the call was completed. Let me illustrate the idea of what is happening behind the scenes.
This is the untransformed code using async/await. The Something method is awaited, so all following code (Bye) will be run after Something completed.
public async Task SomethingAsync()
{
Hello();
await Something();
Bye();
}
To explain this I add a utility class Worker that simply takes some action to run and then notify when done.
public class Worker
{
private Action _action;
public event DoneHandler Done;
// skipping defining DoneHandler delegate
// store the action
public Worker(Action action) => _action = action;
public void Run()
{
// execute the action
_action();
// notify so that following code is run
Done?.Invoke();
}
}
Now our transformed code, not using async/await
public Task SomethingAsync()
{
Hello(); // this remains untouched
// create the worker to run the "awaited" method
var worker = new Worker(() => Something());
// register the rest of our method
worker.Done += () => Bye();
// execute it
worker.Run();
// I left out the part where we return something
// or run the action on a threadpool to keep it simple
}
Here's the short answer:
To answer this you just need to understand what the async / await keywords do.
We know a single thread can only do one thing at a time and we also know that a single thread bounces all over the application to various method calls and events, ETC. This means that where the thread needs to go next is most likely scheduled or queued up somewhere behind the scenes (it is but I won't explain that part here.) When a thread calls a method, that method is ran to completion before any other methods can be ran which is why long running methods are preferred to be dispatched to other threads to prevent the application from freezing. In order to break a single method up into separate queues we need to do some fancy programming OR you can put the async signature on the method. This tells the compiler that at some point the method can be broken up into other methods and placed in a queue to be ran later.
If that makes sense then you're already figuring out what await does... await tells the compiler that this is where the method is going to be broken up and scheduled to run later. This is why you can use the async keyword without the await keyword; although the compiler knows this and warns you. await does all this for you by use of a Task.
How does await use a Task tell the compiler to schedule the rest of the method? When you call await Task the compilers calls the Task.GetAwaiter() method on that Task for you. GetAwaiter() return a TaskAwaiter. The TaskAwaiter implements two interfaces ICriticalNotifyCompletion, INotifyCompletion. Each has one method, UnsafeOnCompleted(Action continuation) and OnCompleted(Action continuation). The compiler then wraps the rest of the method (after the await keyword) and puts it in an Action and then it calls the OnCompleted and UnsafeOnCompleted methods and passes that Action in as a parameter. Now when the Task is complete, if successful it calls OnCompleted and if not it calls UnsafeOnCompleted and it calls those on the same thread context used to start the Task. It uses the ThreadContext to dispatch the thread to the original thread.
Now you can understand that neither async or await execute any Tasks. They simply tell the compiler to use some prewritten code to schedule all of it for you. In fact; you can await a Task that's not running and it will await until the Task is executed and completed or until the application ends.
Knowing this; lets get hacky and understand it deeper by doing what async await does manually.
Using async await
using System;
using System.Threading.Tasks;
namespace Question_Answer_Console_App
{
class Program
{
static void Main(string[] args)
{
Test();
Console.ReadKey();
}
public static async void Test()
{
Console.WriteLine($"Before Task");
await DoWorkAsync();
Console.WriteLine($"After Task");
}
static public Task DoWorkAsync()
{
return Task.Run(() =>
{
Console.WriteLine($"{nameof(DoWorkAsync)} starting...");
Task.Delay(1000).Wait();
Console.WriteLine($"{nameof(DoWorkAsync)} ending...");
});
}
}
}
//OUTPUT
//Before Task
//DoWorkAsync starting...
//DoWorkAsync ending...
//After Task
Doing what the compiler does manually (sort of)
Note: Although this code works it is meant to help you understand async await from a top down point of view. It DOES NOT encompass or execute the same way the compiler does verbatim.
using System;
using System.Threading.Tasks;
namespace Question_Answer_Console_App
{
class Program
{
static void Main(string[] args)
{
Test();
Console.ReadKey();
}
public static void Test()
{
Console.WriteLine($"Before Task");
var task = DoWorkAsync();
var taskAwaiter = task.GetAwaiter();
taskAwaiter.OnCompleted(() => Console.WriteLine($"After Task"));
}
static public Task DoWorkAsync()
{
return Task.Run(() =>
{
Console.WriteLine($"{nameof(DoWorkAsync)} starting...");
Task.Delay(1000).Wait();
Console.WriteLine($"{nameof(DoWorkAsync)} ending...");
});
}
}
}
//OUTPUT
//Before Task
//DoWorkAsync starting...
//DoWorkAsync ending...
//After Task
LESSON SUMMARY:
Note that the method in my example DoWorkAsync() is just a function that returns a Task. In my example the Task is running because in the method I use return Task.Run(() =>…. Using the keyword await does not change that logic. It's exactly the same; await only does what I mentioned above.
If you have any questions just ask and I'll be happy to answer them.
With starting you start a task. That means it might be picked up for execution by whatever Multitasaking system is in place.
With waiting, you wait for one task to actually finish before you continue.
There is no such thing as a Fire and Forget Thread. You always need to come back, to react to exceptions or do somethings with the result of the asynchronous operation (Database Query or WebQuery result, FileSystem operation finished, Dokument send to the nearest printer pool).
You can start and have as many task running in paralell as you want. But sooner or later you will require the results before you can go on.
I have an async method as here below:
protected async Task<string> DoSomeStuff()
{
dynamic info = await fb.GetTaskAsync("me?fields=id,first_name,last_name,link,locale,email,name,birthday,gender,location,age_range,about".GraphAPICall(appsecret_proof));
//this breaks the thread?
string result = "result123";
return result;
//result is always null
}
The await breaks the thread and results into an infinite loop. I can't access the value of result as it is awaiting activation. What am I missing here?
Your controller method should be marked as async and you should await on DoSomeStuff().
E.g.
public async ActionResult YourControllerAction()
{
var result = await DoSomeStuff();
}
The purpose of await is to apply the rest of the code as a continuation if the thing being awaited has not completed. The fact that it suspended execution tells us that the result of dostuff has indeed: not already completed.
The interesting question is: will it ever complete? (either successfully or as an exception is fine). Only you can tell us that. It is possible that dostuff returns something that is never going to complete; for example, you could create a TaskCompletionSource<T> and hand back the .Task without ever actually doing anything that would call SetResult at some future time. What is dostuff?
The await breaks the thread and results into an infinite loop.
An "await" is an "asynchronous wait". In other words, the method is paused but the thread continues executing.
I can't access the value of result as it is awaiting activation.
"Waiting for activation" is the (unfortunately confusing) status for asynchronous tasks that are in progress. I have a blog post on task statuses - in this case, it's a Promise Task, and WaitingForActivation is exactly what you should see if the task has started but has not yet completed.
Since it seems that your task never completes, I would suspect a deadlock. Deadlocks are easily caused by blocking (e.g., Result/Wait) further up your call stack.
I am trying to understand how Async and Await works. How control travel in the program. Here is the code which I was trying to understand.
public async Task MyMethod()
{
Task<int> longRunningTask = LongRunningOperation();
//indeed you can do independent to the int result work here
MySynchronousMethod();
//and now we call await on the task
int result = await longRunningTask;
//use the result
Console.WriteLine(result);
}
public async Task<int> LongRunningOperation() // assume we return an int from this long running operation
{
await Task.Delay(5000); //5 seconds delay
return 1;
}
private void Button_Click_3(object sender, RoutedEventArgs e)
{
MyMethod();
}
When button click occur then MyMethod() will be called and from the MyMethod LongRunningOperation() will be called and it take 5 sec to complete. so my question is
What is the meaning of this line
Task longRunningTask = LongRunningOperation();
what this does int result = await longRunningTask;
The above line could be committed and one line we can construct like
Task<int> longRunningTask = await LongRunningOperation();
or
int result = await longRunningTask;
Please can someone explain to me the above code which is not clear to me.
1) if the longRunningOperation hasn't finished and is still running, MyMethod() will return to its calling method, thus the main thread doesn't get blocked. When the longRunningOperation is done then a thread from the ThreadPool (can be any thread) will return to MyMethod() at its previous state and continue execution (in this case printing the result to the console).
A second case would be that the longRunningOperation has already finished its execution and the result is available. When reaching the await longRunningOperation the compiler knows that it has the result and will keep on executing code on the very same thread. (in this case printing result to console).
point 1 is not at all clear to me like the statement "if the longRunningOperation hasn't finished and is still running, MyMethod() will return to its calling method"
if possible explain the point one in more detail. thanks
I've been taught about it in the following fashion, I found it to be quite a clear and concise explanation:
//this is pseudocode
async Method()
{
code;
code;
await something;
moreCode;
}
When Method is invoked, it executes its contents (code; lines) up to await something;. At that point, something; is fired and the method ends like a return; was there.
something; does what it needs to and then returns.
When something; returns, execution gets back to Method and proceeds from the await onward, executing moreCode;
In a even more schematic fashion, here's what happens:
Method is invoked
code; is executed
something; is executed, flow goes back to the point where Method was invoked
execution goes on with what comes after the Method invocation
when something; returns, flow returns inside Method
moreCode; is executed and Method itself ends (yes, there could be something else await-ing on it too, and so on and so forth)
I have an async intro on my blog that you may find helpful.
This code:
int result = await LongRunningOperation();
is essentially the same as this code:
Task<int> resultTask = LongRunningOperation();
int result = await resultTask;
So, yes, LongRunningOperation is invoked directly by that method.
When the await operator is passed an already-completed task, it will extract the result and continue executing the method (synchronously).
When the await operator is passed an incomplete task (e.g., the task returned by LongRunningOperation will not be complete), then by default await will capture the current context and return an incomplete task from the method.
Later, when the await task completes, the remainder of the method is scheduled to run in that context.
This "context" is SynchronizationContext.Current unless it is null, in which case it is TaskScheduler.Current. If you're running this in a Console app, then the context is usually the thread pool context, so the async method will resume executing on a thread pool thread. However, if you execute the same method on a UI thread, then the context is a UI context and the async method will resume executing on the UI thread.
Behind the scenes C# compiler actually converts your code into a state machine. It generates a lot more code so that behind the scenes every time a await task or async action is completed, it'll continue execution from where it left off. In terms of your question, every time the async action has finished, the async method will be called back on the calling thread when you originally started the call to the async method. Eg it'll execute your code on the thread that you started on. So the async action will be run on a Task thread, then the result will be returned back on the thread you method was originally called on and keep executing.
Await will get the value from the Task or async action and "unbox" it from the task when the execution is returned. In this case it will automatically put it into the int value, so no need to store the Task<int>.
Your code has the problem where it await's on the LongRunningTask() you'd most likely just want to return the long task method without the async, then have your MyMethod perform the await.
int value = await LongWaitingTask()
Async Await and the Generated StateMachine
It's a requirement of async methods that you return a Task or void.
It's possible to change it so when you return back from executing the async task it will execute the remaining code on the thread the async task was performed on using the Task.ConfigureAwait method.
It may be easier to think about it this way:
Whenever you have an await, the compiler splits your method into 2: one part before the await and another part after it.
The second part runs after the first one has finished successfully.
In your code, the first method will look like something roughly equivalent to this:
public async Task MyMethod()
{
Task<int> longRunningTask = LongRunningOperation();
MySynchronousMethod();
longRunningTask.ContinueWith(t => part2(t.Result));
}
void part2(int result)
{
Console.WriteLine(result);
}
Few important notes:
It's obviously much more complex than this since it should support
try-catch and others. Also, it doesn't really use the task
Task is not actually being used directly. It's using the task's GetAwaiter() method and its API, or any other class with this method or extension method.
If there are multiple awaits in a method it's being split multiple times.
If MyMethod is being split, how does someone who awaits MyMethod knows when all parts are done? When your async method returns a Task, the compiler generates a special Task which tracks everything with a state machine.