Ejemplo n.º 1
0
        private Task <string?> DownloadWithProgress(SourceRepository sourceRepository, PackageIdentity packageIdentity)
        {
            var progressDialogText = Resources.Dialog_DownloadingPackage;

            if (packageIdentity.HasVersion)
            {
                progressDialogText = string.Format(CultureInfo.CurrentCulture, progressDialogText, packageIdentity.Id, packageIdentity.Version);
            }
            else
            {
                progressDialogText = string.Format(CultureInfo.CurrentCulture, progressDialogText, packageIdentity.Id, string.Empty);
            }

            string?description = null;
            int?   percent     = null;
            var    updated     = 0;

            var progressDialogLock = new object();

#pragma warning disable CA2000 // Dispose objects before losing scope (handled in finally below)
            var progressDialog = new ProgressDialog
            {
                Text              = progressDialogText,
                WindowTitle       = Resources.Dialog_Title,
                ShowTimeRemaining = true,
                CancellationText  = "Canceling download..."
            };

            // polling for Cancel button being clicked
            var cts   = new CancellationTokenSource();
            var timer = new System.Timers.Timer(100);
#pragma warning restore CA2000 // Dispose objects before losing scope

            timer.Elapsed += (o, e) =>
            {
                lock (progressDialogLock)
                {
                    if (progressDialog.CancellationPending)
                    {
                        timer.Stop();
                        cts.Cancel();
                    }
                    else if (Interlocked.CompareExchange(ref updated, 0, 1) == 1)
                    {
                        progressDialog.ReportProgress(percent.GetValueOrDefault(), null, description);
                    }
                }
            };


            var tcs = new TaskCompletionSource <string?>();
            progressDialog.DoWork += (object?sender, DoWorkEventArgs args) =>
            {
                var t = DoWorkAsync();
                t.Wait(cts.Token);
                tcs.TrySetResult(t.Result);
            };
            progressDialog.RunWorkerCompleted += (object?sender, RunWorkerCompletedEventArgs args) =>
            {
                MainWindow.Value.Activate();
            };

            progressDialog.ShowDialog(MainWindow.Value);
            timer.Start();

            async Task <string?> DoWorkAsync()
            {
                try
                {
                    var httpProgressProvider = new ProgressHttpHandlerResourceV3Provider(OnProgress);
                    var repository           = PackageRepositoryFactory.CreateRepository(sourceRepository.PackageSource, new[] { new Lazy <INuGetResourceProvider>(() => httpProgressProvider) });
                    var downloadResource     = await repository.GetResourceAsync <DownloadResource>(cts !.Token).ConfigureAwait(false);

                    using var sourceCacheContext = new SourceCacheContext()
                          {
                              NoCache = true
                          };
                    var context = new PackageDownloadContext(sourceCacheContext, Path.GetTempPath(), true);

                    using var result = await downloadResource.GetDownloadResourceResultAsync(packageIdentity, context, string.Empty, NullLogger.Instance, cts.Token).ConfigureAwait(false);

                    if (result.Status == DownloadResourceResultStatus.Cancelled)
                    {
                        throw new OperationCanceledException();
                    }

                    if (result.Status == DownloadResourceResultStatus.NotFound)
                    {
                        throw new Exception($"Package '{packageIdentity.Id} {packageIdentity.Version}' not found");
                    }

                    var tempFilePath = Path.GetTempFileName();
                    using (var fileStream = File.OpenWrite(tempFilePath))
                    {
                        await result.PackageStream.CopyToAsync(fileStream).ConfigureAwait(false);
                    }

                    return(tempFilePath);
                }
                catch (OperationCanceledException)
                {
                    return(null);
                }
                catch (Exception exception)
                {
                    OnError(exception);
                    return(null);
                }
                finally
                {
                    timer !.Stop();
                    timer.Dispose();
                    cts !.Dispose();
                    // close progress dialog when done
                    lock (progressDialogLock !)
                    {
                        progressDialog !.Dispose();
                    }
                }
            }

            void OnProgress(long bytesReceived, long?totalBytes)
            {
                if (totalBytes.HasValue)
                {
                    // TODO: remove ! once https://github.com/dotnet/roslyn/issues/33330 is fixed
                    percent     = (int)((bytesReceived * 100L) / totalBytes) !;
                    description = string.Format(
                        CultureInfo.CurrentCulture,
                        "Downloaded {0} of {1}...",
                        FileSizeConverter.Convert(bytesReceived, typeof(string), null, CultureInfo.CurrentCulture),
                        FileSizeConverter.Convert(totalBytes.Value, typeof(string), null, CultureInfo.CurrentCulture));
                }
                else
                {
                    percent     = null;
                    description = string.Format(
                        CultureInfo.CurrentCulture,
                        "Downloaded {0}...",
                        FileSizeConverter.Convert(bytesReceived, typeof(string), null, CultureInfo.CurrentCulture));
                }
                Interlocked.Exchange(ref updated, 1);
            }

            return(tcs.Task);
        }
        private async Task <string> DownloadWithProgress(SourceRepository sourceRepository, PackageIdentity packageIdentity)
        {
            var progressDialogText = Resources.Dialog_DownloadingPackage;

            if (packageIdentity.HasVersion)
            {
                progressDialogText = string.Format(CultureInfo.CurrentCulture, progressDialogText, packageIdentity.Id, packageIdentity.Version);
            }
            else
            {
                progressDialogText = string.Format(CultureInfo.CurrentCulture, progressDialogText, packageIdentity.Id, string.Empty);
            }

            string description = null;
            int?   percent     = null;
            var    updated     = false;

            var progressDialogLock = new object();
            var progressDialog     = new ProgressDialog
            {
                Text              = progressDialogText,
                WindowTitle       = Resources.Dialog_Title,
                ShowTimeRemaining = true,
                CancellationText  = "Canceling download..."
            };

            // polling for Cancel button being clicked
            var cts   = new CancellationTokenSource();
            var timer = new DispatcherTimer
            {
                Interval = TimeSpan.FromMilliseconds(200)
            };

            timer.Tick += (o, e) =>
            {
                lock (progressDialogLock)
                {
                    if (progressDialog.CancellationPending)
                    {
                        timer.Stop();
                        cts.Cancel();
                    }
                    else if (updated)
                    {
                        if (!progressDialog.IsOpen)
                        {
                            progressDialog.ProgressBarStyle = percent.HasValue ? ProgressBarStyle.ProgressBar : ProgressBarStyle.MarqueeProgressBar;
                            progressDialog.ShowDialog(MainWindow.Value);
                        }
                        progressDialog.ReportProgress(percent.GetValueOrDefault(), null, description);
                        updated = false;
                    }
                }
            };
            timer.Start();

            try
            {
                var httpProgressProvider = new ProgressHttpHandlerResourceV3Provider(OnProgress);
                var additionalProviders  = new[] { new Lazy <INuGetResourceProvider>(() => httpProgressProvider) };

                var repository       = PackageRepositoryFactory.CreateRepository(sourceRepository.PackageSource, additionalProviders);
                var downloadResource = await repository.GetResourceAsync <DownloadResource>(cts.Token);

                using (var sourceCacheContext = new SourceCacheContext()
                {
                    NoCache = true
                })
                {
                    var context = new PackageDownloadContext(sourceCacheContext, Path.GetTempPath(), true);

                    using (var result = await downloadResource.GetDownloadResourceResultAsync(packageIdentity, context, string.Empty, NullLogger.Instance, cts.Token))
                    {
                        if (result.Status == DownloadResourceResultStatus.Cancelled)
                        {
                            throw new OperationCanceledException();
                        }
                        if (result.Status == DownloadResourceResultStatus.NotFound)
                        {
                            throw new Exception(string.Format("Package '{0} {1}' not found", packageIdentity.Id, packageIdentity.Version));
                        }

                        var tempFilePath = Path.GetTempFileName();

                        using (var fileStream = File.OpenWrite(tempFilePath))
                        {
                            await result.PackageStream.CopyToAsync(fileStream);
                        }

                        return(tempFilePath);
                    }
                }
            }
            catch (OperationCanceledException)
            {
                return(null);
            }
            catch (Exception exception)
            {
                OnError(exception);
                return(null);
            }
            finally
            {
                timer.Stop();

                // close progress dialog when done
                lock (progressDialogLock)
                {
                    progressDialog.Close();
                    progressDialog = null;
                }

                MainWindow.Value.Activate();
            }

            void OnProgress(long bytesReceived, long?totalBytes)
            {
                if (totalBytes.HasValue)
                {
                    percent     = (int)((bytesReceived * 100L) / totalBytes);
                    description = string.Format(
                        CultureInfo.CurrentCulture,
                        "Downloaded {0} of {1}...",
                        FileSizeConverter.Convert(bytesReceived, typeof(string), null, CultureInfo.CurrentCulture),
                        FileSizeConverter.Convert(totalBytes.Value, typeof(string), null, CultureInfo.CurrentCulture));
                }
                else
                {
                    percent     = null;
                    description = string.Format(
                        CultureInfo.CurrentCulture,
                        "Downloaded {0}...",
                        FileSizeConverter.Convert(bytesReceived, typeof(string), null, CultureInfo.CurrentCulture));
                }
                updated = true;
            }
        }