//--------------------------------------------------------Misc Methods:---------------------------------------------------------------\\ #region --Misc Methods (Public)-- public async Task EnqueueDownloadAsync(AbstractDownloadableObject o) { SetDownloadState(o, DownloadState.QUEUED); await TO_DOWNLOAD_SEMA.WaitAsync(); TO_DOWNLOAD.Add(o); TO_DOWNLOAD_SEMA.Release(); TO_DOWNLOAD_COUNT_SEMA.Release(); }
private void SetDownloadState(AbstractDownloadableObject o, DownloadState newState) { if (o.state != newState) { DownloadStateChangedEventArgs args = new DownloadStateChangedEventArgs(o.state, newState); o.state = newState; DownloadStateChanged?.Invoke(o, args); } }
private async Task DownloadAsync(AbstractDownloadableObject o) { Logger.Info("Started downloading <" + o.targetFileName + "> from: " + o.sourceUrl); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(o.sourceUrl); HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync(); long bytesReadTotal = 0; // Check that the remote file was found. // The ContentType check is performed since a request for a non-existent image file might be redirected to a 404-page, which would yield the StatusCode "OK", even though the image was not found. if (response.StatusCode == HttpStatusCode.OK || response.StatusCode == HttpStatusCode.Moved || response.StatusCode == HttpStatusCode.Redirect) { StorageFile file = await GenFilePathAsync(o.targetFolderPath, o.targetFileName); if (file is null) { o.error = DownloadError.FAILED_TO_CREATE_LOCAL_PATH; SetDownloadState(o, DownloadState.ERROR); return; } using (Stream inputStream = response.GetResponseStream()) using (Stream outputStream = await file.OpenStreamForWriteAsync()) { byte[] buffer = new byte[4096]; int bytesRead; do { bytesRead = await inputStream.ReadAsync(buffer, 0, buffer.Length); await outputStream.WriteAsync(buffer, 0, bytesRead); // Update progress: bytesReadTotal += bytesRead; UpdateDownloadProgress(o, response.ContentLength, bytesReadTotal); } while (bytesRead != 0 && o.state != DownloadState.CANCELED); } if (o.state == DownloadState.CANCELED) { Logger.Info("Canceled downloading <" + o.targetFileName + "> from: " + o.sourceUrl); return; } SetDownloadState(o, DownloadState.DONE); Logger.Info("Finished downloading <" + o.targetFileName + "> from: " + o.sourceUrl); } else { o.error = DownloadError.INVALID_STATUS_CODE; SetDownloadState(o, DownloadState.ERROR); Logger.Error("Unable to download image <" + o.targetFileName + "> from: " + o.sourceUrl + "- Status code check failed: " + response.StatusCode + "(" + response.StatusDescription + ')'); } }
//--------------------------------------------------------Set-, Get- Methods:---------------------------------------------------------\\ #region --Set-, Get- Methods-- public async Task <AbstractDownloadableObject> FindAsync(Predicate <AbstractDownloadableObject> predicate) { AbstractDownloadableObject result = null; await TO_DOWNLOAD_SEMA.WaitAsync(); result = TO_DOWNLOAD.Find(predicate); TO_DOWNLOAD_SEMA.Release(); if (!(result is null)) { return(result); } DOWNLOADING_SEMA.Wait(); result = DOWNLOADING.Find(predicate); DOWNLOADING_SEMA.Release(); return(result); }
/// <summary> /// Starts a new downloader Task and returns it. /// </summary> /// <param name="index">The index of the downloader Task.</param> /// <returns>Returns a new downloader Task.</returns> private Task StartDownlaoderTask(int index) { return(Task.Run(async() => { while (!DOWNLOADER_CANCELLATION_TOKENS[index].IsCancellationRequested) { try { // Wait until downloads are available: await TO_DOWNLOAD_COUNT_SEMA.WaitAsync(); Logger.Debug("Downloader task " + index + " started job."); // Remove one download: await TO_DOWNLOAD_SEMA.WaitAsync(); AbstractDownloadableObject o = TO_DOWNLOAD[0]; TO_DOWNLOAD.RemoveAt(0); TO_DOWNLOAD_SEMA.Release(); if (o.state != DownloadState.CANCELED) { SetDownloadState(o, DownloadState.DOWNLOADING); o.progress = 0; // Add to currently downloading: await DOWNLOADING_SEMA.WaitAsync(); DOWNLOADING.Add(o); DOWNLOADING_SEMA.Release(); // Download: await DownloadAsync(o); // Remove since the download finished: await DOWNLOADING_SEMA.WaitAsync(); DOWNLOADING.Remove(o); DOWNLOADING_SEMA.Release(); } Logger.Debug("Downloader task " + index + " finished job."); } catch (Exception e) { Logger.Error("Downloader task " + index + " job failed with: ", e); } } }, DOWNLOADER_CANCELLATION_TOKENS[index].Token)); }
public void CancelDownload(AbstractDownloadableObject o) { SetDownloadState(o, DownloadState.CANCELED); }
/// <summary> /// Calculates the new download progress and sets it for the given AbstractDownloadableObject. /// </summary> /// <param name="o">The AbstractDownloadableObject.</param> /// <param name="totalSize">The total size of the download in bytes.</param> /// <param name="bytesDownloadedTotal">How many bytes have been downloaded?</param> /// <returns>Returns the last progress update percentage.</returns> private double UpdateDownloadProgress(AbstractDownloadableObject o, long totalSize, long bytesDownloadedTotal) { o.progress = bytesDownloadedTotal / ((double)totalSize) * 100; return(o.progress); }