/// <summary> /// Releases unmanaged and - optionally - managed resources. /// </summary> /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> protected virtual void Dispose(bool dispose) { if (dispose) { lock (CurrentInstallations) { foreach (var tuple in CurrentInstallations) { tuple.Item2.Dispose(); } CurrentInstallations.Clear(); } } }
/// <summary> /// Installs the package. /// </summary> /// <param name="package">The package.</param> /// <param name="progress">The progress.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> /// <exception cref="System.ArgumentNullException">package</exception> public async Task InstallPackage(PackageVersionInfo package, IProgress <double> progress, CancellationToken cancellationToken) { if (package == null) { throw new ArgumentNullException("package"); } if (progress == null) { throw new ArgumentNullException("progress"); } var installationInfo = new InstallationInfo { Id = Guid.NewGuid().ToString("N"), Name = package.name, AssemblyGuid = package.guid, UpdateClass = package.classification, Version = package.versionStr }; var innerCancellationTokenSource = new CancellationTokenSource(); var tuple = new Tuple <InstallationInfo, CancellationTokenSource>(installationInfo, innerCancellationTokenSource); // Add it to the in-progress list lock (CurrentInstallations) { CurrentInstallations.Add(tuple); } var innerProgress = new ActionableProgress <double>(); // Whenever the progress updates, update the outer progress object and InstallationInfo innerProgress.RegisterAction(percent => { progress.Report(percent); installationInfo.PercentComplete = percent; }); var linkedToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, innerCancellationTokenSource.Token).Token; var installationEventArgs = new InstallationEventArgs { InstallationInfo = installationInfo, PackageVersionInfo = package }; EventHelper.FireEventIfNotNull(PackageInstalling, this, installationEventArgs, _logger); try { await InstallPackageInternal(package, innerProgress, linkedToken).ConfigureAwait(false); lock (CurrentInstallations) { CurrentInstallations.Remove(tuple); } progress.Report(100); CompletedInstallations.Add(installationInfo); EventHelper.FireEventIfNotNull(PackageInstallationCompleted, this, installationEventArgs, _logger); } catch (OperationCanceledException) { lock (CurrentInstallations) { CurrentInstallations.Remove(tuple); } _logger.Info("Package installation cancelled: {0} {1}", package.name, package.versionStr); EventHelper.FireEventIfNotNull(PackageInstallationCancelled, this, installationEventArgs, _logger); throw; } catch (Exception ex) { _logger.ErrorException("Package installation failed", ex); lock (CurrentInstallations) { CurrentInstallations.Remove(tuple); } EventHelper.FireEventIfNotNull(PackageInstallationFailed, this, new InstallationFailedEventArgs { InstallationInfo = installationInfo, Exception = ex }, _logger); throw; } finally { // Dispose the progress object and remove the installation from the in-progress list innerProgress.Dispose(); tuple.Item2.Dispose(); } }