When to use ValueTask?
Despite having used C# for a while I'm... not that familiar with async. I know people sometimes say to sometimes use
ValueTask<T>
instead of Task<T>
, but when should you exactly do this? The extent of my knowledge (and reading the docs) is that ValueTask<T>
is like a DU between either a T
value or a Task<T>
, so is it ideal for situations in which an async method may just return a cached value?37 Replies
And since you can use
ValueTask<T>
as the result of an async method, is the compiler smart enough to generate the appropriate code based on whether such a cached value is used without any async calls being used?It's more that it's a cheaper alternative to Task, but more limited
Mind elaborating?
It doesn't allocate (as much, at least), but you can't do things like await it twice, or use it with e.g. Task.WhenAll
https://devblogs.microsoft.com/dotnet/understanding-the-whys-whats-and-whens-of-valuetask/ is a pretty good overview, if you haven't read it.
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
If I essentially have this Is it worth using
ValueTask
?Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
Nice
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
Why would you await it twice anyway?
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
canton7#1569
In that case, it's normal to cache the task. That way, if someone queries the value while it's still being loaded by a previous query, that won't result in the value being calculated a second time in parallel: instead the second caller gets given the same Task which was given to the first caller, which will complete when the value becomes available. If the value is already fetched, awaiting the task just completes synchronously and gives the value straight away
Quoted by
<@!660066004059029524> from #advanced (click here)
React with ❌ to remove this embed.
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
Assuming you mean
return Task.FromResult(cachedValue);
But that makes senseUnknown User•3y ago
Message Not Public
Sign In & Join Server To View
An already completed task?
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
Well, it'll complete when it completes. That's the point
My own rules are:
I know the async func will almost never complete synchronously => Task
If I know it will return synchronously most of the time => ValueTask
if it's internal function and I already didn't decided with 2 previous point => ValueTask
No. cachedValue is a
Task<string>
(otherwise none of the other lines would compile)
The point is that if someone calls GetStringAsync (which calls DoSomeOtherOperationAsync) you immediately cache the work-in-progress task. Then if someone else calls GetStringAsync before the task has completed, you give them back the same Task rather than calling DoSomeOtherOperationAsync a second time. If the task has completed, great, awaiting it is a free noop
My view here is that single allocations are staggeringly cheap, and bugs are expensive. I'll always go with Task unless it's a high-perf scenario, in which case I'll have my profiler out and it can tell me if I need to move to ValueTask🤨 cachedValue is a string not Task<string>
if you are directly awaiting the task
var value = await GetStringAsync();
use a valuetask
if you need to use the task
var task = GetStringAsync();
// await task later
then use a normal task
@thinker227 - relevant, not sure if anyone mentioned this but
1) - As such, the default choice for any asynchronous method should be to return a Task or Task<TResult> (https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.valuetask-1?view=net-6.0)
2) Microsoft uses a
ValueTask
in the ProtectedBrowserStorage
class in ASP.Net core for the method that is called to retrieve cached values... I think you mentioned something about cacheing so just wanted to point out that is how MSFT is using it in this case.ValueTask Struct (System.Threading.Tasks)
Provides a value type that wraps a Task and a TResult, only one of which is used.
from my own personal asking around and seeing other people converse on the topic:
use ValueTask if you expect your method to return synchronously a greater-than-negligible amount of times. Use Task otherwise. ValueTask can, to my knowledge, offer a performance/speed gain over Task (if the method performs synchronous work only), but this is only noticible at massive scales where your method is called a LOT. it's not worth fretting over otherwise
Another funny thing is that Microsoft is calling methods
SetAsync
when they are not marked with a async
modifier which is pretty bizarre..A modern API? Not an older EAP/APM API?
difference between task and valuetask is that task allocates a new object on every call but valuetask only allocates a new object if the operation was asynchronous
otherwise the call is allocation free
I'm saying turn it into a Task<string>
Do they return a Task maybe?
No, they return a ValueTask… and it isn’t marked with async so if something bizarre happens they are tying up the whole thread… they also suffix the method with Async so it looks like a Async method but it isn’t.. I’m sure though there is something I’m missing because this seems really bad. If you go to the .NET open source and type in the search ProtectedBrowserStorage you will see it. I’m on a phone, otherwise I would send the link
https://github.com/dotnet/aspnetcore/blob/c85baf8db0c72ae8e68643029d514b2e737c9fae/src/Components/Server/src/ProtectedBrowserStorage/ProtectedBrowserStorage.cs#L59 so these are mostly passthrough methods where
async
is ellided for perf. I assume MS knows how to do that properly...tagging the method names with Async
can be confusing.^ This is what I thought when reading your message
I think this is totally fine
how do you mark a thread as done
right click on it => archive
I figured that out and then yall posted again ._.