public TypedData Process(TypedData data, IMutableProgressTracker progress, CancellationToken cancelToken) { // ToList is needed to prevent new MPT's from being // created for each loop of commandProgressTrackers var commandProgressTrackers = this.commands.Select((command) => new { ProgressTracker = new MutableProgressTracker(), Command = command }).ToList(); var aggregateProgress = new AggregateProgressTracker(commandProgressTrackers.Select( (cpt) => new ProgressTrackerCollectionItem( cpt.ProgressTracker, cpt.Command.ProcessTimeEstimate.ProgressWeight ) )); aggregateProgress.BindTo(progress); bool shouldDisposeData = false; foreach (var cpt in commandProgressTrackers) { cancelToken.ThrowIfCancellationRequested(); TypedData newData; try { cancelToken.ThrowIfCancellationRequested(); if (!cpt.Command.IsValid()) { throw new CommandInvalidException(cpt.Command); } newData = cpt.Command.Process(data, cpt.ProgressTracker, cancelToken); cancelToken.ThrowIfCancellationRequested(); } finally { if (shouldDisposeData && data != null) { data.Dispose(); } } data = newData; shouldDisposeData = true; } return data; }