/// <inheritdoc /> public Task <TValue> LoadAsync(TKey key) { if (key == null) { throw new ArgumentNullException(nameof(key)); } lock (_sync) { TKey resolvedKey = _cacheKeyResolver(key); if (_options.Caching && _cache.TryGetValue(resolvedKey, out Task <TValue> cachedValue)) { DispatchingDiagnostics.RecordCachedValue(resolvedKey, cachedValue); return(cachedValue); } var promise = new TaskCompletionSource <TValue>( TaskCreationOptions.RunContinuationsAsynchronously); if (_options.Batching) { if (!_buffer.TryAdd(resolvedKey, promise) && _buffer.TryGetValue(resolvedKey, out TaskCompletionSource <TValue> value)) { promise.TrySetCanceled(); promise = value; } } else { // note: must run in the background; do not await here. Task.Factory.StartNew( () => DispatchAsync(resolvedKey, promise), TaskCreationOptions.RunContinuationsAsynchronously); } if (_options.Caching) { _cache.TryAdd(resolvedKey, promise.Task); } return(promise.Task); } }
public bool TryAddSingle() { return(_buffer.TryAdd(_keys[0], new TaskCompletionSource <int>( TaskCreationOptions.RunContinuationsAsynchronously))); }
/// <inheritdoc /> public Task <TValue> LoadAsync( TKey key, CancellationToken cancellationToken) { if (key == null) { throw new ArgumentNullException(nameof(key)); } lock (_sync) { object cacheKey = _cacheKeyResolver(key); if (_options.Caching && _cache.TryGetValue( cacheKey, out Task <TValue>?cachedValue)) { DiagnosticEvents.ReceivedValueFromCache( key, cacheKey, cachedValue); return(cachedValue); } var promise = new TaskCompletionSource <TValue>( TaskCreationOptions.RunContinuationsAsynchronously); if (_options.Batching) { if (!_buffer.TryAdd(key, promise) && _buffer.TryGetValue( key, out TaskCompletionSource <TValue>?value)) { promise.TrySetCanceled(); promise = value; } else { RaiseRequestBuffered(); } } else { CancellationToken combinedToken = _disposeTokenSource .CreateLinkedCancellationToken(cancellationToken); // must run decoupled from this task, so that LoadAsync // responds immediately; do not await here. Task.Factory.StartNew( () => DispatchSingleAsync( key, promise, combinedToken), TaskCreationOptions.RunContinuationsAsynchronously); } if (_options.Caching) { _cache.TryAdd(cacheKey, promise.Task); } return(promise.Task); } }