Esempio n. 1
0
            private static IReadOnlyCollection <m3u8_part_ts> download_m3u8File_parallel(m3u8_client mc, m3u8_file_t m3u8_file
                                                                                         , CancellationTokenSource cts = null, int maxDegreeOfParallelism = 64)
            {
                var ct               = (cts?.Token).GetValueOrDefault(CancellationToken.None);
                var baseAddress      = m3u8_file.BaseAddress;
                var totalPatrs       = m3u8_file.Parts.Count;
                var globalPartNumber = 0;
                var downloadPartsSet = new SortedSet <m3u8_part_ts>(default(m3u8_part_ts.comparer));

                using (DefaultConnectionLimitSaver.Create(maxDegreeOfParallelism))
                {
                    Parallel.ForEach(m3u8_file.Parts, new ParallelOptions()
                    {
                        MaxDegreeOfParallelism = maxDegreeOfParallelism, CancellationToken = ct
                    },
                                     (part, loopState, idx) =>
                    {
                        var n = Interlocked.Increment(ref globalPartNumber);
                        try
                        {
                            CONSOLE.WriteLine($"#{n} of {totalPatrs}). '{part.RelativeUrlName}'...");
                            var downloadPart = mc.DownloadPart(part, baseAddress, ct).Result;
                            if ((downloadPart.Error != null) && !ct.IsCancellationRequested)
                            {
                                CONSOLE.WriteLineError($"#{n} of {totalPatrs}). FAILED: {downloadPart.Error}{Environment.NewLine}");
                            }

                            lock ( downloadPartsSet )
                            {
                                downloadPartsSet.Add(downloadPart);
                            }
                        }
                        catch (Exception ex)
                        {
                            #region [.code.]
                            var aex = ex as AggregateException;
                            if ((aex == null) || !aex.InnerExceptions.All(e => (e is OperationCanceledException)))
                            {
                                CONSOLE.WriteLineError("ERROR: " + ex);
                            }
                            #endregion
                        }
                    });
                }

                ct.ThrowIfCancellationRequested();

                CONSOLE.WriteLine($"\r\n total parts processed: {globalPartNumber} of {totalPatrs}");

                return(downloadPartsSet);
            }
Esempio n. 2
0
            private static IEnumerable <m3u8_part_ts> download_m3u8File_parallel__v2(m3u8_client mc, m3u8_file_t m3u8_file
                                                                                     , CancellationTokenSource cts = null, int maxDegreeOfParallelism = 64)
            {
                var ct                = (cts?.Token).GetValueOrDefault(CancellationToken.None);
                var baseAddress       = m3u8_file.BaseAddress;
                var totalPatrs        = m3u8_file.Parts.Count;
                var successPartNumber = 0;

                var expectedPartNumber = m3u8_file.Parts.FirstOrDefault().OrderNumber;
                var maxPartNumber      = m3u8_file.Parts.LastOrDefault().OrderNumber;
                var sourceQueue        = new Queue <m3u8_part_ts>(m3u8_file.Parts);
                var downloadPartsSet   = new SortedSet <m3u8_part_ts>(default(m3u8_part_ts.comparer));

                using (DefaultConnectionLimitSaver.Create(maxDegreeOfParallelism))
                    using (var canExtractPartEvent = new AutoResetEvent(false))
                        using (var semaphore = new SemaphoreSlim(maxDegreeOfParallelism))
                        {
                            var task_download = Task.Run(() =>
                            {
                                for ( ; sourceQueue.Count != 0;)
                                {
                                    semaphore.Wait();
                                    var part = sourceQueue.Dequeue();
#if DEBUG
                                    CONSOLE.WriteLine($"start download part: {part}...");
#endif
                                    mc.DownloadPart(part, baseAddress, ct)
                                    .ContinueWith(t =>
                                    {
                                        if (t.IsFaulted)
                                        {
                                            Interlocked.Increment(ref expectedPartNumber);

                                            CONSOLE.WriteLine($"'{t.Exception.GetType().Name}': '{t.Exception.Message}'.", ConsoleColor.Red);
                                        }
                                        else if (!t.IsCanceled)
                                        {
                                            Interlocked.Increment(ref successPartNumber);

                                            var downloadPart = t.Result;
#if DEBUG
                                            CONSOLE.WriteLine($"end download part: {downloadPart}.");
#endif
                                            lock ( downloadPartsSet )
                                            {
                                                downloadPartsSet.Add(downloadPart);
                                                canExtractPartEvent.Set();
                                            }
                                        }
                                    });
                                }
                            }, ct);

                            for ( ; expectedPartNumber <= maxPartNumber && !ct.IsCancellationRequested;)
                            {
#if DEBUG
                                CONSOLE.WriteLine($"wait part #{expectedPartNumber}...");
#endif
                                canExtractPartEvent.WaitOne();

                                lock ( downloadPartsSet )
                                {
                                    for ( ; downloadPartsSet.Count != 0;)
                                    {
                                        var min_part = downloadPartsSet.Min;
                                        if (expectedPartNumber == min_part.OrderNumber)
                                        {
                                            CONSOLE.WriteLine($"receive part #{expectedPartNumber}.");

                                            downloadPartsSet.Remove(min_part);

                                            Interlocked.Increment(ref expectedPartNumber);

                                            semaphore.Release();

                                            yield return(min_part);
                                        }
                                        else
                                        {
                                            break;
                                        }
                                    }
                                }
                            }
                        }

                ct.ThrowIfCancellationRequested();

                CONSOLE.WriteLine($"\r\n total parts processed: {successPartNumber} of {totalPatrs}");
            }