private IDownloadCancelHandle StartEnqueuedDownload(QueuedDownload download) { _downloadStartedEvent.OnNext(download); App.Engine.StatisticsManager.LogDownloadStart(download); Transport.PendingDownload pendingDownload = Transport.StartQueuedDownload(download); pendingDownload.Response .ObserveOnDispatcher() .Subscribe <Transport.RunningDownload>( activeDownload => { if (activeDownload.Download.DownloadSize == long.MaxValue || activeDownload.Download.DownloadSize == 0) { activeDownload.Download.DownloadSize = activeDownload.ContentLength; } BackgroundWorker worker = new BackgroundWorker() { WorkerReportsProgress = true, WorkerSupportsCancellation = true }; // change cancel handle startedDownloads[activeDownload.Download] = new ActiveDownloadCancelHandle(worker); worker.DoWork += (sender, e) => { Transport.RunningDownload dl = (Transport.RunningDownload)e.Argument; BackgroundWorker bw = (BackgroundWorker)sender; long bytesRead = dl.Download.DownloadedBytes; // limited number of progress bar updates var uiUpdates = new Subject <long>(); var cancelUiUpdates = uiUpdates .Take(1) .Merge(Observable.Empty <long>().Delay(TimeSpan.FromMilliseconds(KProgressUpdateInterval))) .Repeat() .Subscribe <long>(progress => { if (bw.IsBusy) { bw.ReportProgress(0, progress); } }); if (dl is Transport.ActiveDownload) { string filePath = Utils.MediaFilePath(App.Engine.LoggedUser, dl.Download); using (Stream writer = new IsolatedStorageFileStream(filePath, FileMode.Append, IsolatedStorageFile.GetUserStoreForApplication())) { using (Stream reader = ((Transport.ActiveDownload)dl).Stream) { byte[] buffer = new byte[16 * 1024]; int readCount; while ((readCount = reader.Read(buffer, 0, buffer.Length)) > 0) { bytesRead += readCount; writer.Write(buffer, 0, readCount); uiUpdates.OnNext(bytesRead); if (bw.CancellationPending) { pendingDownload.Cancel(); e.Cancel = true; break; } } bw.ReportProgress(0, bytesRead); e.Result = activeDownload.Download; } } cancelUiUpdates.Dispose(); } if (dl is Transport.BackgroundDownload) { BackgroundTransferRequest downloadRequest = ((Transport.BackgroundDownload)dl).Request; IObservable <IEvent <BackgroundTransferEventArgs> > requestObserver = Observable.FromEvent <BackgroundTransferEventArgs>(downloadRequest, "TransferStatusChanged"); if (downloadRequest.TransferStatus != TransferStatus.Completed) { if (downloadRequest.TransferStatus == TransferStatus.None) { downloadRequest.DownloadLocation = new Uri(Utils.BackgroundFilePath(App.Engine.LoggedUser, dl.Download), UriKind.RelativeOrAbsolute); downloadRequest.TransferPreferences = TransferPreferences.AllowCellularAndBattery; e.Result = activeDownload.Download; BackgroundTransferService.Add(downloadRequest); } downloadRequest.TransferProgressChanged += (senderBackground, eventBackground) => { if (activeDownload.Download.DownloadSize == long.MaxValue || activeDownload.Download.DownloadSize == 0) { activeDownload.Download.DownloadSize = activeDownload.ContentLength == -1 ? 0: activeDownload.ContentLength; } uiUpdates.OnNext(eventBackground.Request.BytesReceived); }; IDisposable cancelOnStop = DownloadStopPendingEvent.Subscribe(stoppedDownload => { if (dl.Download == stoppedDownload) { BackgroundTransferService.Remove(downloadRequest); dl.Download.State = QueuedDownload.DownloadState.Stopped; dl.Download.DownloadedBytes = 0; } }); bw.ReportProgress(0, requestObserver.First().EventArgs.Request); cancelOnStop.Dispose(); } e.Result = activeDownload.Download; } }; worker.ProgressChanged += (sender, e) => { if (e.UserState is BackgroundTransferRequest) { BackgroundTransferRequest request = e.UserState as BackgroundTransferRequest; if (request.TransferStatus != TransferStatus.Completed || request.TransferError is InvalidOperationException) { activeDownload.Download.DownloadedBytes = 0; } else { activeDownload.Download.DownloadedBytes = ((BackgroundTransferRequest)e.UserState).BytesReceived; } } else { activeDownload.Download.DownloadedBytes = (long)e.UserState; } }; worker.RunWorkerCompleted += (sender, e) => { if (activeDownload is Transport.ActiveDownload) { startedDownloads.Remove(activeDownload.Download); if (!IsFileDownloadSuccessfulOrResumed(e, activeDownload.Download)) { _downloadStoppedEvent.OnNext(activeDownload.Download); } } else { if (!e.Cancelled && e.Error == null) { startedDownloads.Remove(activeDownload.Download); QueuedDownload result = (QueuedDownload)e.Result; if (IsBackgroundTransferSuccesfull(((Transport.BackgroundDownload)activeDownload).Request, result)) { _downloadCompletedEvent.OnNext(activeDownload.Download); App.Engine.StatisticsManager.LogDownloadCompleted(activeDownload.Download, "Completed"); } else { _downloadStoppedEvent.OnNext(activeDownload.Download); } } else if (e.Error != null) { startedDownloads.Remove(download); _downloadErrorEvent.OnNext(download); } else { try { BackgroundTransferService.Remove((activeDownload as Transport.BackgroundDownload).Request); _downloadStoppedEvent.OnNext(activeDownload.Download); startedDownloads.Remove(download); } catch (InvalidOperationException) { startedDownloads.Remove(download); } } } }; worker.RunWorkerAsync(activeDownload); }, error => { startedDownloads.Remove(download); if (IsFileMissingFromServer(error)) { _downloadErrorEvent.OnNext(download); App.Engine.StatisticsManager.LogDownloadCompleted(download, "Error"); } else { _downloadStoppedEvent.OnNext(download); } } ); return(new PendingDownloadCancelHandle(pendingDownload)); }
public PendingDownloadCancelHandle(Transport.PendingDownload download) { this.download = download; }