Question regarding tasks
Please consider the code below. Won't the usersTask run twice? And since I need its return value, isn't it unnecessary to run it within a Task.WhenAll() method?
30 Replies
Yes, this will run twice. Once in the
WhenAll()
, once with this individual await
And yes, if you just need to get the users, then WhenAll()
is completely redundant
Just
will doHey @ZZZZZZZZZZZZZZZZZZZZZZZZZ, thanks for your answer. I found this via google: https://stackoverflow.com/a/38306418/11436180, can I ask you for your thoughts?
Stack Overflow
What happens when awaiting on already-completed task?
When I construct an instance of a class that I have, I would like to trigger a Token renewal function (async method) and let it run in the background (I keep a reference to the returned Task).
Lat...
Yeah I'll believe it
Especially the below part, as I think it contradicts somehow with your answer.
if you await a task that is already completed it returns immediately. You could await it several times on different threads and it would only return once it has the result (or is faulted).
I don't think I ever had to call an async method that's already been awaited before, so I have no first-hand experience of how it works
the only Task you have to pay attention to is ValueTask
you can't await it multiple times
but in general await multiple times is kinda the wrong pattern
Okay, thank you for your answer. Your willingness to help is seriously appreciated!
but in general await multiple times is kinda the wrong patternThe thought behind my original code is that the tasks will run in parallell, but the point of the
await usersTask
is to retrieve its results. Since it has been established that it will immediately return the result, then I think there's no problem.
And thank you for your information regarding the ValueTask.you can use .Result once the task has been awaited
Cool, I'll try it!
I just had a discussion with ChatGPT. I asked if .Result can be used instead of await. I'll include a screenshot. Can I ask what you think?
Instead of
await
? Hell the fuck noPlease also see this:
Okay, I sense a preferance towards the code posted in my original message.
Can I be so entitled and ask for an explanation to this?
.Result
is blocking
await
ing frees the thread to do other work while the method executes
.Result
blocks the thread, not freeing it upThanks man
When the task is already awaited, then getting the
.Result
from it should technically be fine, since the long-running job is already done
But I'm in favour of just blanket-banning it from the codebase with an analyzerOkay thanks.
It sounds like I'm gonna take a deep-dive into C#'s source code in order to research things.
Glad you could help.
$nothread
There Is No Thread
This is an essential truth of async in its purest form: There is no thread.
if you want a deep dive into async
Thanks for the link!
Man, someone from Microsoft Support should be able to answer these questions. Having worked in the techinical support branch myself, it would be my job to answer these kinds of questions.
Tried checking the source code – too much work.
imo there's one time when it makes sense to use .Result, and it's when using task.whenall
private async Task<int> foobar()
{
return 4;
}
private void dosomething(int x){}
private async Task whatever() { var first = foobar(); var second = foobar(); await Task.WhenAll(first, second);
dosomething(first.Result); dosomething(second.Result); } in this context, you know .Result is safe and Task.WhenAll returns an array, so getting the values you care about from there is a pain i find this style a lot more convenient you could use 'dosomething(await first);' or whatever but i tend to dislike that yeah i would not try to learn async by reading the implementation 🙂 there are some good blogposts that are a better introduction. cleary's blog linked above is a good knowledge source as well
private void dosomething(int x){}
private async Task whatever() { var first = foobar(); var second = foobar(); await Task.WhenAll(first, second);
dosomething(first.Result); dosomething(second.Result); } in this context, you know .Result is safe and Task.WhenAll returns an array, so getting the values you care about from there is a pain i find this style a lot more convenient you could use 'dosomething(await first);' or whatever but i tend to dislike that yeah i would not try to learn async by reading the implementation 🙂 there are some good blogposts that are a better introduction. cleary's blog linked above is a good knowledge source as well
Stephen Toub - MSFT
.NET Blog
How Async/Await Really Works in C# - .NET Blog
Async/await was added to the C# language over a decade ago and has transformed how we write scalable code for .NET. But how does it really work? In this post, we take a deep dive into its internals.
as is anything by stephen toub
I think this code example is clean. It shows how the tasks first be awaited and then their .Result properties be read afterwards.
yeah
it's a somewhat niche situation but it's good to know it's possible
I wish there was some way to have a
WhenAll
that would give the results back
Like int[] nums = Task.WhenAll<int>(first, second)
Limited to tasks of the same generic type of course@ZZZZZZZZZZZZZZZZZZZZZZZZZ, yeah, I've looked for the same thing myself – typed out WhenAll in the IDE. Looked at the hints. Checked if it is possible to return the results.
If one is eager, one could apply a push request to C#'s GitHub and suggest this – though it would require some well written documentation.
Unknown User•5mo ago
Message Not Public
Sign In & Join Server To View
just do
myValueTask.AsTask()
and you're fine
write it yourself, it's a good exercise for getting into TPL apis :)