Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
09/20/17 15:12:10 (7 years ago)
Author:
pfleck
Message:

#2822

  • Correctly triggers optimizer task exception within continuation.
  • Using lazy evaluation to re-include "externally started but then paused" optimizers.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/ParallelExperiment/HeuristicLab.Optimization/3.3/MetaOptimizers/Experiment.cs

    r15373 r15375  
    204204      if ((ExecutionState != ExecutionState.Prepared) && (ExecutionState != ExecutionState.Paused))
    205205        throw new InvalidOperationException(string.Format("Start not allowed in execution state \"{0}\".", ExecutionState));
    206       if (!Optimizers.Any(x => x.ExecutionState == ExecutionState.Prepared || x.ExecutionState == ExecutionState.Paused)) return;
     206
     207      // Multiple enumerations of runnableOptimizers is done on purpose to get the latest list of runnnable optimizers lazily
     208      var runnableOptimizers = Optimizers.Where(x => x.ExecutionState == ExecutionState.Prepared || x.ExecutionState == ExecutionState.Paused);
     209      if (!runnableOptimizers.Any()) return;
    207210
    208211      experimentStarted = true;
    209212      experimentStopped = false;
    210213
    211       var startedTasks = new List<Task>();
     214      var startedOptimizers = new Dictionary<IOptimizer, Task>(); // track already started optimizers (.StartAsync does not set the executionstate immediately)
    212215      using (var availableWorkers = new SemaphoreSlim(NumberOfWorkers, NumberOfWorkers)) {
    213         var runnableOptimizers = Optimizers.Where(o => o.ExecutionState == ExecutionState.Prepared || o.ExecutionState == ExecutionState.Paused).ToList();
    214         if (!runnableOptimizers.Any()) return;
    215 
    216         while (runnableOptimizers.Any()) {
     216        while (runnableOptimizers.Any(o => !startedOptimizers.ContainsKey(o))) {
    217217          try {
    218218            availableWorkers.Wait(cancellationToken);
    219219            if (experimentStopped || !experimentStarted) break;
    220             // some optimizers might be started manually somewhere else
    221             runnableOptimizers.RemoveAll(o => !(o.ExecutionState == ExecutionState.Prepared || o.ExecutionState == ExecutionState.Paused));
    222             if (runnableOptimizers.Any()) {
    223               var optimizer = runnableOptimizers.First();
    224               runnableOptimizers.Remove(optimizer);
    225               var startedTask = optimizer.StartAsync(cancellationToken).ContinueWith(x => {
    226                 availableWorkers.Release(); // is not disposed yet because Task.WaitAll at the end of the using is blocking
     220            var optimizer = runnableOptimizers.FirstOrDefault(o => !startedOptimizers.ContainsKey(o));
     221            if (optimizer != null) {
     222              var startedTask = optimizer.StartAsync(cancellationToken).ContinueWith(async t => {
     223                availableWorkers.Release(); // is guaranteed to be not disposed yet because Task.WaitAll blocks before the end of the using
     224                await t; // trigger a potential exception on the optimizerTask
    227225              });
    228               startedTasks.Add(startedTask);
     226              startedOptimizers.Add(optimizer, startedTask.Unwrap()); // unwrap task because lambda of .ContinueWith is async
    229227            }
    230228          } catch (InvalidOperationException) { } catch (OperationCanceledException) { }
    231229        }
    232230
     231        Task.WaitAll(startedOptimizers.Values.ToArray()); // retreive exeptions of the asyncrounously started optimizer
    233232        allOptimizerFinished.Wait();
    234         Task.WaitAll(startedTasks.ToArray()); // retreive exeptions of the asyncrounously started optimizer
    235233      }
    236234    }
Note: See TracChangeset for help on using the changeset viewer.