/// <summary>
        /// Pause is stop
        /// </summary>
        /// <param name="_targetResource"></param>
        /// <returns></returns>
        public ExecuteResult DownloadPause(T _targetResource)
        {
            if (_targetResource.ResourceInfo == null)
            {
                return(ExecuteResult.Faile);
            }

            lock (m_lockList)
            {
                string _resourceKey = _targetResource.ResourceInfo.ResourceKey;
                if (m_DownloadResourceList.ContainsKey(_resourceKey))
                {
                    var _item = m_DownloadResourceList[_resourceKey];
                    if (_item != null)
                    {
                        _item.DownloadStop();
                        OnDownloadStatusChanged.Invoke(this, new DownloadStatusChangedEventArgs(_item, DownloadStatus.DownloadPause));
                        m_DownloadResourceList.Remove(_resourceKey);
                        return(ExecuteResult.Success);
                    }
                }

                return(ExecuteResult.Faile);
            }
        }
        private void updateDownloadStatus()
        {
            if (_downloadStatus.RemoteFileSize <= 0 || _downloadStatus.BytesTransferred <= 0)
            {
                return;
            }

            _downloadStatus.PercentComplete =
                Math.Round((decimal)_downloadStatus.BytesTransferred * 100 / (decimal)_downloadStatus.RemoteFileSize, 2);

            var elapsedTime = DateTimeOffset.UtcNow - _downloadStatus.StartTime;

            _downloadStatus.BytesPerSecond = _downloadStatus.BytesTransferred / elapsedTime.TotalSeconds;

            var rawEta = _downloadStatus.RemoteFileSize / _downloadStatus.BytesPerSecond;

            _downloadStatus.EstimatedCompletionTime = TimeSpan.FromSeconds(rawEta);

            OnDownloadStatusChanged?.Invoke(_downloadStatus);
        }
        /// <summary>
        /// If add resource successed, start downloading immediately.
        /// </summary>
        /// <param name="_targetResource"></param>
        /// <returns></returns>
        public ExecuteResult AddResource(T _targetResource)
        {
            if (_targetResource.ResourceInfo == null)
            {
                return(ExecuteResult.Faile);
            }

            lock (m_lockList)
            {
                if (m_DownloadResourceList.ContainsKey(_targetResource.ResourceInfo.ResourceKey))
                {
                    OnDownloadStatusChanged.Invoke(this, new DownloadStatusChangedEventArgs(_targetResource, DownloadStatus.Downloading));
                    return(ExecuteResult.Success);
                }

                var minPriorityResource = GetMinPriorityInDownloadingList();
                if (IsTargetRescourceHighPriority(_targetResource.ResourceInfo, minPriorityResource.ResourceInfo))
                {
                    // target resource higher, stop the minimum priority in downloading list, change status to WaitForDownload.
                    LogInstance.Instance.LogInfo($"Stop downloading list resource that min priority[{minPriorityResource.ResourceInfo.ResourceKey}] and start downloan target resource[{_targetResource.ResourceInfo.ResourceKey}].");
                    minPriorityResource.DownloadStop();
                    OnDownloadStatusChanged.Invoke(this, new DownloadStatusChangedEventArgs(minPriorityResource, DownloadStatus.WaitForDownload));

                    m_DownloadResourceList.Add(_targetResource.ResourceInfo.ResourceKey, _targetResource);
                    _targetResource.OnDownloadingStatusChanged += OnDownloadStatusChanged;
                    _targetResource.DownloadStart();
                    OnDownloadStatusChanged.Invoke(this, new DownloadStatusChangedEventArgs(_targetResource, DownloadStatus.Downloading));
                    return(ExecuteResult.Success);
                }
                else
                {
                    // the minimum priority higher, change target resource to WaitForDownload.
                    LogInstance.Instance.LogInfo($"Target resource[{_targetResource.ResourceInfo.ResourceKey}] will wait for download.");
                    OnDownloadStatusChanged.Invoke(this, new DownloadStatusChangedEventArgs(_targetResource, DownloadStatus.WaitForDownload));
                    return(ExecuteResult.Success);
                }
            }
        }