Exemplo n.º 1
0
        /// <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 object?cachedValue))
                {
                    var cachedTask = (Task <TValue>)cachedValue;

                    DiagnosticEvents.ReceivedValueFromCache(key, cacheKey, cachedTask);

                    return(cachedTask);
                }

                TaskCompletionSource <TValue> promise = GetOrCreatePromise(key);

                if (_options.Caching)
                {
                    _cache.TryAdd(cacheKey, promise.Task);
                }

                return(promise.Task);
            }
        }
Exemplo n.º 2
0
        /// <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);
            }
        }