public IDisposable SetDownloadProgress([CanBeNull] IProgress <AsyncProgressEntry> progress, long?suggestedTotal = null, Action callback = null) { var s = Stopwatch.StartNew(); void Handler(object sender, DownloadProgressChangedEventArgs args) { if (s.Elapsed.TotalMilliseconds < 20) { return; } callback?.Invoke(); s.Restart(); var total = args.TotalBytesToReceive; if (total == -1 && suggestedTotal != null && suggestedTotal > 0) { total = Math.Max(suggestedTotal.Value, args.BytesReceived); } progress?.Report(AsyncProgressEntry.CreateDownloading(args.BytesReceived, total)); } DownloadProgressChanged += Handler; return(new ActionAsDisposable(() => { DownloadProgressChanged -= Handler; })); }
public static async Task <string> LoadAsyncTo(string argument, FlexibleLoaderGetPreferredDestinationCallback getPreferredDestination, [CanBeNull] FlexibleLoaderReportDestinationCallback reportDestination, Action <FlexibleLoaderMetaInformation> reportMetaInformation = null, Func <bool> checkIfPaused = null, IProgress <AsyncProgressEntry> progress = null, CancellationToken cancellation = default) { progress?.Report(AsyncProgressEntry.FromStringIndetermitate("Finding fitting loader…")); var loader = await CreateLoaderAsync(argument, cancellation) ?? throw new OperationCanceledException(); try { using (var order = KillerOrder.Create(new CookieAwareWebClient(), TimeSpan.FromMinutes(10))) { var client = order.Victim; if (_proxy != null) { client.Proxy = _proxy; } progress?.Report(AsyncProgressEntry.Indetermitate); cancellation.ThrowIfCancellationRequested(); cancellation.Register(client.CancelAsync); if (!await loader.PrepareAsync(client, cancellation)) { throw new InformativeException("Can’t load file", "Loader preparation failed."); } cancellation.ThrowIfCancellationRequested(); reportMetaInformation?.Invoke(FlexibleLoaderMetaInformation.FromLoader(loader)); var initialProgressCallback = true; var reportStopwatch = Stopwatch.StartNew(); var progressStopwatch = new AsyncProgressBytesStopwatch(); if (loader.UsesClientToDownload) { client.DownloadProgressChanged += (sender, args) => { if (initialProgressCallback) { reportMetaInformation?.Invoke(FlexibleLoaderMetaInformation.FromLoader(loader)); initialProgressCallback = false; } if (reportStopwatch.Elapsed.TotalMilliseconds < 20) { return; } order.Delay(); reportStopwatch.Restart(); progress?.Report(AsyncProgressEntry.CreateDownloading(args.BytesReceived, args.TotalBytesToReceive == -1 && loader.TotalSize.HasValue ? Math.Max(loader.TotalSize.Value, args.BytesReceived) : args.TotalBytesToReceive, progressStopwatch)); }; } var loaded = await loader.DownloadAsync(client, getPreferredDestination, reportDestination, checkIfPaused, loader.UsesClientToDownload?null : new Progress <long>(p => { if (initialProgressCallback) { reportMetaInformation?.Invoke(FlexibleLoaderMetaInformation.FromLoader(loader)); initialProgressCallback = false; } if (reportStopwatch.Elapsed.TotalMilliseconds < 20) { return; } order.Delay(); reportStopwatch.Restart(); progress?.Report(loader.TotalSize.HasValue ? AsyncProgressEntry.CreateDownloading(p, loader.TotalSize.Value, progressStopwatch) : new AsyncProgressEntry(string.Format(UiStrings.Progress_Downloading, p.ToReadableSize(1)), null)); }), cancellation); cancellation.ThrowIfCancellationRequested(); Logging.Write("Loaded: " + loaded); return(loaded); } } catch (Exception e) when(cancellation.IsCancellationRequested || e.IsCancelled()) { Logging.Warning("Cancelled"); throw new OperationCanceledException(); } catch (Exception e) { Logging.Warning(e); throw; } }
public static async Task <string> LoadAsyncTo(string argument, string destination, IProgress <AsyncProgressEntry> progress = null, Action <FlexibleLoaderMetaInformation> metaInformationCallback = null, CancellationToken cancellation = default(CancellationToken)) { var loader = CreateLoader(argument); try { using (var order = KillerOrder.Create(new CookieAwareWebClient { Headers = { [HttpRequestHeader.UserAgent] = CmApiProvider.UserAgent } }, TimeSpan.FromMinutes(10))) { var client = order.Victim; if (_proxy != null) { client.Proxy = _proxy; } progress?.Report(AsyncProgressEntry.Indetermitate); cancellation.ThrowIfCancellationRequested(); cancellation.Register(client.CancelAsync); if (!await loader.PrepareAsync(client, cancellation)) { throw new InformativeException("Can’t load file", "Loader preparation failed."); } cancellation.ThrowIfCancellationRequested(); metaInformationCallback?.Invoke(new FlexibleLoaderMetaInformation(loader.TotalSize, loader.FileName, loader.Version)); var s = Stopwatch.StartNew(); if (loader.UsesClientToDownload) { client.DownloadProgressChanged += (sender, args) => { if (s.Elapsed.TotalMilliseconds > 20) { order.Delay(); s.Restart(); } else { return; } var total = args.TotalBytesToReceive; if (total == -1 && loader.TotalSize != -1) { total = Math.Max(loader.TotalSize, args.BytesReceived); } progress?.Report(AsyncProgressEntry.CreateDownloading(args.BytesReceived, total)); }; } await loader.DownloadAsync(client, destination, loader.UsesClientToDownload?null : new Progress <double>(p => { if (s.Elapsed.TotalMilliseconds > 20) { order.Delay(); s.Restart(); } else { return; } var total = loader.TotalSize; progress?.Report(total == -1 ? new AsyncProgressEntry("Loading…", p) : AsyncProgressEntry.CreateDownloading((long)(p * total), total)); }), cancellation); cancellation.ThrowIfCancellationRequested(); } } catch (Exception) when(cancellation.IsCancellationRequested) { throw new OperationCanceledException(); } return(destination); }
public static async Task <string> LoadAsyncTo(string argument, string destination, IProgress <AsyncProgressEntry> progress = null, CancellationToken cancellation = default(CancellationToken)) { var loader = CreateLoader(argument); try { // TODO: Timeout? using (var client = new CookieAwareWebClient { Headers = { [HttpRequestHeader.UserAgent] = CmApiProvider.UserAgent } }) { progress?.Report(AsyncProgressEntry.Indetermitate); cancellation.ThrowIfCancellationRequested(); cancellation.Register(client.CancelAsync); if (!await loader.PrepareAsync(client, cancellation) || cancellation.IsCancellationRequested) { return(null); } var skipEvent = 0; client.DownloadProgressChanged += (sender, args) => { if (++skipEvent > 50) { skipEvent = 0; } else { return; } var total = args.TotalBytesToReceive; if (total == -1 && loader.TotalSize != -1) { total = Math.Max(loader.TotalSize, args.BytesReceived); } // ReSharper disable once AccessToDisposedClosure progress?.Report(AsyncProgressEntry.CreateDownloading(args.BytesReceived, total)); }; await loader.DownloadAsync(client, destination, cancellation); if (cancellation.IsCancellationRequested) { return(null); } Logging.Debug("Loaded: " + destination); } return(destination); } catch (TaskCanceledException) { return(null); } catch (Exception e) { NonfatalError.Notify(ToolsStrings.Common_CannotDownloadFile, ToolsStrings.Common_CannotDownloadFile_Commentary, e); return(null); } }