1y ago · Nov 5, 2024 4:45 PM
A common question for intermediate C# developers: when should you return instead of ?
The Rule:
- Use Task<T> when the method is expected to complete asynchronously >80% of the time (e.g. database network queries, disk file I/O).
- Use ValueTask<T> when the method completes **synchronously in the majority of cases** (e.g. memory cache hits, pre-buffered socket reads).
Crucial Rule with ValueTask: Never await a twice, and never call before awaiting, because the underlying value struct may be pooled and recycled!
CODE
ValueTask<T> CODE
Task<T>The Rule:
- Use Task<T> when the method is expected to complete asynchronously >80% of the time (e.g. database network queries, disk file I/O).
- Use ValueTask<T> when the method completes **synchronously in the majority of cases** (e.g. memory cache hits, pre-buffered socket reads).
CSHARP
public class CacheService
{
private readonly ConcurrentDictionary<string, byte[]> _memoryCache = new();
public ValueTask<byte[]> GetCachedDataAsync(string key)
{
// Fast path: In-memory cache hit (Zero heap allocation!)
if (_memoryCache.TryGetValue(key, out byte[]? data))
{
return new ValueTask<byte[]>(data);
}
// Slow path: Fallback to async disk/network load
return new ValueTask<byte[]>(LoadFromRemoteAsync(key));
}
private async Task<byte[]> LoadFromRemoteAsync(string key) { ... }
}Crucial Rule with ValueTask: Never await a
CODE
ValueTask CODE
.Result
AsyncMaster · Concurrency Geek
Task Parallel Library (TPL), async/await internals, and lock...
Task Parallel Library (TPL), async/await internals, and lock...
The following users thanked AsyncMaster for this post: