/// <summary>
        /// Requests for the cache data using specified key.
        /// </summary>
        public CacheListener <TValue> Request(TKey key)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            // Remove last data or request first.
            if (Listener != null)
            {
                Remove();
            }

            Key      = key;
            Listener = Cacher.Request(key);
            if (Listener.IsFinished)
            {
                InvokeFinished(Listener.Value);
                InvokeProgress(1f);
            }
            else
            {
                Listener.OnFinished += InvokeFinished;
                Listener.OnProgress -= InvokeProgress;
            }
            return(Listener);
        }
        public void RemoveDelayed(CacheListener <TValue> listener, float delay = 2f)
        {
            if (listener == null)
            {
                throw new ArgumentNullException(nameof(listener));
            }

            var timer = CreateTimer();

            timer.Limit       = delay;
            timer.OnFinished += () => Remove(listener);
            timer.Start();
        }
        public void Remove(CacheListener <TValue> listener)
        {
            if (listener == null)
            {
                throw new ArgumentNullException(nameof(listener));
            }

            if (requests.TryGetValue(listener.Key, out CacheRequest <TValue> request))
            {
                RemoveListener(listener, request);
                return;
            }
        }
        /// <summary>
        /// Creates a new listener that listens to the completion of this request.
        /// </summary>
        public CacheListener <T> Listen()
        {
            AssertNotDisposed();

            var listener = new CacheListener <T>(Key);

            if (IsComplete)
            {
                listener.SetFinished(Value);
            }

            Listeners.Add(listener);
            return(listener);
        }
        /// <summary>
        /// Removes the specified listener from the request.
        /// </summary>
        private void RemoveListener(CacheListener <TValue> listener, CacheRequest <TValue> request)
        {
            // Remove listener
            request.Unlisten(listener);

            // If no more reference remaining on the resource, then revoke the request.
            if (request.Listeners.Count <= 0)
            {
                if (request.IsComplete)
                {
                    DestroyData(request.Value);
                }
                request.Dispose();
                requests.Remove(request.Key);
            }
        }
        /// <summary>
        /// Removes the last cached data fetched from the cacher using the last specified key.
        /// </summary>
        public void Remove()
        {
            if (Listener != null)
            {
                Listener.OnFinished -= InvokeFinished;
                Listener.OnProgress -= InvokeProgress;

                if (UseDelayedRemove)
                {
                    Cacher.RemoveDelayed(Listener, RemoveDelay);
                }
                else
                {
                    Cacher.Remove(Listener);
                }
            }
            Key      = null;
            Listener = null;
        }
        /// <summary>
        /// Attempts to remove the specified listener, if managed by this request.
        /// </summary>
        public bool Unlisten(CacheListener <T> listener)
        {
            AssertNotDisposed();

            return(Listeners.Remove(listener));
        }