public void DownloadSongs(IList <Track> tracksToDownload, CancellationTokenSource syncCancellationSource)
        {
            Interlocked.Add(ref ManifestUtil.ProgressUtil.SongsToDownload, tracksToDownload.Count);

            if (ManifestUtil.ProgressUtil.SongsToDownload == 0)
            {
                return;
            }
            if (ConcurrentDownloads == 0)
            {
                throw new Exception(LanguageManager.Language["STR_DOWNLOAD_SONG_EX"]);
            }
            var po = new ParallelOptions
            {
                CancellationToken      = syncCancellationSource.Token,
                MaxDegreeOfParallelism = ConcurrentDownloads
            };

            try
            {
                Parallel.ForEach(tracksToDownload, po,
                                 track =>
                {
                    try
                    {
                        po.CancellationToken.ThrowIfCancellationRequested();
                        ManifestUtil.ProgressUtil.AddOrUpdateInProgressTrack(track);

                        DownloadTrackAndTag(ref track);
                        //if not downloadable
                        //ManifestUtil.ProgressUtil.AddOrUpdateNotDownloadableTrack(track);
                        //Interlocked.Decrement(ref ManifestUtil.ProgressUtil.SongsToDownload);

                        track.IsDownloaded = true;
                        ManifestUtil.ProgressUtil.AddOrUpdateSuccessFullTrack(track);
                        ProcessUpdateManifestDelegate pumd = ManifestUtil.UpdateManifest;
                        pumd(track);
                    }
                    catch (Exception e)
                    {
                        ManifestUtil.ProgressUtil.AddOrUpdateFailedTrack(track, e);
                        ManifestUtil.FileSystemUtil.LogTrackException(track, e);

                        double exceptionPercentage = ((double)ManifestUtil.ProgressUtil.CurrentAmountOfExceptions / (double)ManifestUtil.ProgressUtil.SongsProcessing) * 100;
                        if (exceptionPercentage >= ProgressUtils.MaximumExceptionThreshHoldPercentage)
                        {
                            ManifestUtil.ProgressUtil.HasErrors = true;
                            syncCancellationSource.Cancel();
                        }
                    }
                });
            }
            catch (OperationCanceledException e)
            {
                ManifestUtil.ProgressUtil.ThrowAllExceptionsWithRootException(e);
            }
            finally
            {
            }
        }
        public void DownloadSongs(IList <Track> tracksToDownload)
        {
            Interlocked.Add(ref ManifestUtil.ProgressUtil.SongsToDownload, tracksToDownload.Count);

            if (ManifestUtil.ProgressUtil.SongsToDownload == 0)
            {
                return;
            }
            var cts = new CancellationTokenSource();

            if (ConcurrentDownloads == 0)
            {
                throw new Exception("Number for concurrent downloads must be at least 1");
            }
            var po = new ParallelOptions
            {
                CancellationToken      = cts.Token,
                MaxDegreeOfParallelism = ConcurrentDownloads
            };

            try
            {
                Parallel.ForEach(tracksToDownload, po,
                                 track =>
                {
                    try
                    {
                        ManifestUtil.ProgressUtil.AddOrUpdateInProgressTrack(track);

                        if (!DownloadTrackAndTag(ref track))
                        {
                            return;
                        }

                        track.IsDownloaded = true;

                        ManifestUtil.ProgressUtil.AddOrUpdateSuccessFullTrack(track);
                        ProcessUpdateManifestDelegate pumd = ManifestUtil.UpdateManifest;
                        pumd(track);
                    }
                    catch (Exception e)
                    {
                        ManifestUtil.ProgressUtil.AddOrUpdateFailedTrack(track, e);
                        ManifestUtil.FileSystemUtil.LogTrackWithError(track, e);

                        //EventLog.WriteEntry(Application.ProductName, exc.ToString());
                        if (ProgressUtils.MaximumExceptionsCount <= ManifestUtil.ProgressUtil.CurrentAmountOfExceptions)
                        {
                            ManifestUtil.ProgressUtil.IsError = true;
                            cts.Cancel();
                            po.CancellationToken.ThrowIfCancellationRequested();
                        }
                    }
                });
            }
            catch (OperationCanceledException e)
            {
                ManifestUtil.ProgressUtil.ThrowAllExceptionsWithRootException(e);
            }
            finally
            {
                cts.Dispose();
            }
        }