Example #1
0
        /// <summary>
        /// Transfer the downloaded song to the given <see cref="SongTarget"/>s.
        /// </summary>
        /// <param name="targets"></param>
        /// <param name="downloadContainer"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        /// <exception cref="OperationCanceledException"></exception>
        protected async Task <TargetResult[]> TransferToTargets(IEnumerable <SongTarget> targets, DownloadContainer downloadContainer, CancellationToken cancellationToken)
        {
            List <TargetResult> completedTargets = new List <TargetResult>(_targets.Length);

            foreach (SongTarget?target in targets)
            {
                cancellationToken.ThrowIfCancellationRequested();
                TargetResult result = await target.TransferAsync(Song, downloadContainer.GetResultStream(), cancellationToken).ConfigureAwait(false);

                completedTargets.Add(result);
                _stageIndex++;
                ReportProgress(JobProgress.CreateTargetCompletion(CurrentProgress, result));
            }
            return(completedTargets.ToArray());
        }
Example #2
0
        /// <summary>
        /// Starts the job.
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task RunAsync(CancellationToken cancellationToken)
        {
            JobState = JobState.Running;
            if (CancellationToken.CanBeCanceled)
            {
                CancellationTokenSource?cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, CancellationToken);
                cancellationToken = cts.Token;
                cts.Dispose();
                cts = null;
            }
            JobStage = JobStage.Downloading;
            Exception?   exception = null;
            bool         canceled  = false;
            EventHandler?handler   = JobStarted;

            handler?.Invoke(this, null);
            DownloadContainer?  downloadContainer = null;
            List <TargetResult> completedTargets  = new List <TargetResult>(_targets.Length);
            List <SongTarget>   pendingTargets    = new List <SongTarget>(_targets.Length);

            foreach (SongTarget?target in _targets)
            {
                SongState songState = await target.CheckSongExistsAsync(Song).ConfigureAwait(false);

                if (songState != SongState.Wanted)
                {
                    completedTargets.Add(new TargetResult(target, songState, true, null));
                }
                else
                {
                    pendingTargets.Add(target);
                }
            }
            try
            {
                cancellationToken.ThrowIfCancellationRequested();
                if (string.IsNullOrEmpty(Song.Key))
                {
                    SongInfoResponse?result = await WebUtils.SongInfoManager.GetSongByHashAsync(Song.Hash, cancellationToken).ConfigureAwait(false);

                    if (result.Success)
                    {
                        Song.Key = result.Song?.Key;
                    }
                }
                if (pendingTargets.Count > 0)
                {
                    _downloadJob.JobProgressChanged += _downloadJob_JobProgressChanged;
                    DownloadResult = await _downloadJob.RunAsync(cancellationToken).ConfigureAwait(false);

                    downloadContainer = DownloadResult.DownloadContainer;
                    if (DownloadResult.Exception != null)
                    {
                        throw DownloadResult.Exception;
                    }
                    _stageIndex = 1;
                    ReportProgress(JobProgress.CreateDownloadCompletion(CurrentProgress, DownloadResult));
                    JobStage = JobStage.TransferringToTargets;
                    foreach (TargetResult?targetResult in completedTargets)
                    {
                        _stageIndex++;
                        ReportProgress(JobProgress.CreateTargetCompletion(CurrentProgress, targetResult));
                    }
                    completedTargets.AddRange(await TransferToTargets(pendingTargets, downloadContainer, cancellationToken).ConfigureAwait(false));
                }
                else
                {
                    DownloadResult = new DownloadResult(null, DownloadResultStatus.Skipped, 0);
                    _stageIndex    = 1;
                    _downloadJob_JobProgressChanged(this, new DownloadJobProgressChangedEventArgs(DownloadJobStatus.Finished));
                    JobStage = JobStage.TransferringToTargets;
                    foreach (TargetResult?targetResult in completedTargets)
                    {
                        _stageIndex++;
                        ReportProgress(JobProgress.CreateTargetCompletion(CurrentProgress, targetResult));
                    }
                }
                TargetResult[] failedTargets = completedTargets.Where(t => !t.Success).ToArray();
                if (failedTargets.Length > 0)
                {
                    Exception?firstException = failedTargets.FirstOrDefault(t => t.Exception != null)?.Exception;
                    if (firstException != null)
                    {
                        throw firstException;
                    }
                }
                TargetResults = completedTargets.ToArray();
            }
            catch (OperationCanceledException ex)
            {
                if (TargetResults == null && completedTargets.Count > 0)
                {
                    TargetResults = completedTargets.ToArray();
                }
                else
                {
                    TargetResults = Array.Empty <TargetResult>();
                }

                canceled  = true;
                exception = ex;
                ReportProgress(JobProgress.CreateFromFault(JobProgressType.Cancellation, JobStage, CurrentProgress));
                JobState = JobState.Cancelled;
            }
            catch (Exception ex)
            {
                if (TargetResults == null && completedTargets.Count > 0)
                {
                    TargetResults = completedTargets.ToArray();
                }
                else
                {
                    TargetResults = Array.Empty <TargetResult>();
                }
                exception = ex;
                JobState  = JobState.Error;
                ReportProgress(JobProgress.CreateFromFault(JobProgressType.Error, JobStage, CurrentProgress));
            }
            finally
            {
                JobStage = JobStage.Finishing;
                try
                {
                    downloadContainer?.Dispose();
                }
                catch { }
                if (DownloadResult == null)
                {
                    // TODO: What was this for?
                }
                FinishJob(canceled, exception);
                JobFinishedAsyncCallback?asyncCallback = JobFinishedAsyncCallback;
                if (asyncCallback != null)
                {
                    await asyncCallback(Result).ConfigureAwait(false);
                }
            }
        }