Asynchronous calls with await [duplicate] - c#

This question already has answers here:
How Async and Await works
(4 answers)
Closed 7 years ago.
I have one question about await keyword. Here is some test code:
string username = await GetUsernameAsync();
// Some other code
var some_variable = username;
My question is: Does waiting starts at first line where we called async method or at the third line where we need the result of async method? Does some other code executes after GetUsernameAsync finishes its execution, or they are executing in parallel?

It happens at the line where the await is.
If you want to delay the waiting, move the await to the moment you need the result. Remember the task, and move on. Then if you need the result, await the task:
Task<string> usernameTask = GetUsernameAsync();
// Some other code
var some_variable = await usernameTask;

The first one. Take into account the await is just sugar syntax. It will be, more or less, replaced by a Task.Wait() to obtain the result. In fact, GetUsernameAsync() will return a Task, not a string.
Take a look to this link to deep more how threads work with the asyn/await pattern

Related

How to wrap a synchronous function to async function in C#? [duplicate]

This question already has an answer here:
Awaiting a Callback method
(1 answer)
Closed 1 year ago.
am using a synchronous 3rd function which I cannot modify, such as:
public void startDoSth(Action<string> onDone)
startDoSth spawn a new thread to do the job, and returns immediately, and when the thing is done, my onDone function would be called.
I'd like to write an asynchronous method like below to wrap it:
public async Task<string> doSthAsync();
So, someone can call it like this:
string s = await doSthAsync()
onDone(s)
In doSthasync() I call startDoSth() to do the real thing.
But I have no idea how to write the doSthAsync().
Could anyone tell if it is possible and how to do it? Thanks a lot.
You can use TaskCompletionSource to convert that into TAP:
Task<string> DoSthAsync()
{
var tcs = new TaskCompletionSource<string>();
startDoSth(tcs.SetResult);
return tcs.Task;
}
SetResult completes the returned Task (and sets the result), so that can be passed as the callback function.

Await doesn't block calling thread [duplicate]

This question already has answers here:
How and when to use ‘async’ and ‘await’
(25 answers)
How do yield and await implement flow of control in .NET?
(5 answers)
Brief explanation of Async/Await in .Net 4.5
(3 answers)
Closed 2 years ago.
I never had a good chance to go deep into async/await , so I have just a gist of what it does.
So I tried it in WinForms app like this:
private async void button2_Click(object sender, EventArgs e)
{
// In below line I understand the Task is created and scheduled to execute, which in this
// simple case means, that it executes right away asynchronously.
var task = Task.Factory.StartNew(() =>
{
Task.Delay(5000).Wait();
return 12;
});
// Here we wait for the task to finish, so we don't see MessageBox yet.
var res = await task;
MessageBox.Show("Result is :" + res);
}
My question is, since we are waiting on await I expected to block UI thread, since we can go any further in that thread (to the line with MessageBox). So UI thread actually stops on method with event hadnler.
But, to my surprise, windows is responsive and everything works very well, but I didn't expect that. Can anybody explain me what is going on?
After reading this post, I still have a doubt, if await is asynchronous and doesn't block UI thread in my example, why the thread doesn't proceed to next line with MessageBox? How the UI thread proceeds then?
Is good idea that code after await is just another Task, like in ContinueWith? But it comes back to UI context?
Async methods are a lot like generator methods. The compiler will split up your code at each await operator. A block of code is inserted to check if the task is already complete, in which case the method immediately continues. Or if the task is not complete, a callback is registered to continue execution later, and your method returns.
Returning early is the whole point of an async method.

Does GetAwaiter() throw a single exception? [duplicate]

This question already has answers here:
Is Task.Result the same as .GetAwaiter.GetResult()?
(7 answers)
Closed 3 years ago.
I am trying to understand why the following Task.Run and GetAwaiter().GetResult() would be used instead of await ... <result>
(var success, var response) = Task.Run(() => HTTPHelper.SendRequest<SomeJsonResponse>( ... )).GetAwaiter().GetResult();
Does the code above throw, as this article shows, an Exception and not an AggregateException? If so, I believe that is why this structure was chosen.
Is it possible to use async ... await in this situation and have the same result? (I assume not, if the single exception requirement is only possible with the code above.)
Yeah, you can and should use async await :
(var success, var response) = await HTTPHelper.SendRequest<SomeJsonResponse>( ... )
Then there is no need to wrap it into the Task. I assume .SendRequest<SomeJsonResponse>() returns the Task.
FYI: .Wait(), .Result or GetAwaiter().GetResult() are all thread blocking executions

UI Received task got cancelled [duplicate]

This question already has answers here:
'await' works, but calling task.Result hangs/deadlocks
(6 answers)
Closed 3 years ago.
In my application, I am trying to update the user profile which calls the Rest API. API has one sync method UpdateProfile where execution getting stuck.
this line of code is ending the execution
command.UserProfile.LookupItems = GetLookupItemsByUserId(existingUser.Id).Result;
When i changed this line of code to
command.UserProfile.LookupItems = Task.Run(async () => await GetLookupItemsByUserId(existingUser.Id)).Result;
It started working without any issue.Can anybody explain to me what is going on behind the scene?
The first version is blocking the current thread, when the task complete the blocked thread cannot catch it.
YourType Signature() {
var neverUsedValue = task.Result;
}
The second one is yielding the current "thread" until the task is returned.
YourType Signature() {
var value = Task.Run(await => async MethodThatWillComplete()).Result
}
What you should do is propagate the async to the method:
async Task<YourType> SignatureAsync() {
command.UserProfile.LookupItems = await GetLookupItemsByUserId(existingUser.Id);
}
In this way you will avoid handling the AggregateException.
There is very well written article on this here:Don't block async
In a few words, blocking on async code is bad because it may be blocking the thread which is supposed to run the async code and thus generete a deadlock.

What is the difference between WaitAll and WhenAll? [duplicate]

This question already has answers here:
WaitAll vs WhenAll
(4 answers)
Closed 6 years ago.
I have this code:
List<ComponentesClasificaciones> misClasificaciones = new List<ComponentesClasificaciones>();
Task tskClasificaciones = Task.Run(() =>
{
misClasificaciones = VariablesGlobales.Repositorio.buscarComponentesClasificacionesTodosAsync().Result;
});
Task.WhenAll(tskClasificaciones);
List<ComponentesClasificaciones> misVClasificacionesParaEstructuras = new List<ComponentesClasificaciones>(misClasificaciones);
If I use Task.WhenAll, misClasificaciones does not have any element but when I use awit all I get all the elements that I request to the database.
When to use WhenAll and when to use WaitAll?
MSDN does a good job of explaining this. The difference is pretty unambiguous.
Task.WhenAll:
Creates a task that will complete when all of the supplied tasks have completed.
Task.WaitAll:
Waits for all of the provided Task objects to complete execution.
So, essentially, WhenAll gives you a task that isn't done until all of the tasks you give it are done (and allows program execution to continue immediately), whereas WaitAll just blocks and waits for all of the tasks you pass to finish.
WhenAll returns a task that you can ContinueWith once all the specified tasks are complete. You should be doing
Task.WhenAll(tskClasificaciones).ContinueWith(t => {
// code here
});
Basically, use WaitAll when you want to synchronously get the results, use WhenAll when you want to start a new asynchronous task to start some more processing

Categories