Index: /trunk/sources/HeuristicLab.Optimization.Views/3.3/ExperimentView.cs
===================================================================
--- /trunk/sources/HeuristicLab.Optimization.Views/3.3/ExperimentView.cs	(revision 15451)
+++ /trunk/sources/HeuristicLab.Optimization.Views/3.3/ExperimentView.cs	(revision 15452)
@@ -78,5 +78,6 @@
     #region Events
     private void workersNumericUpDown_ValueChanged(object sender, System.EventArgs e) {
-      Content.NumberOfWorkers = (int)workersNumericUpDown.Value;
+      if (Content != null)
+        Content.NumberOfWorkers = (int)workersNumericUpDown.Value;
     }
     #endregion
Index: /trunk/sources/HeuristicLab.Optimization/3.3/MetaOptimizers/Experiment.cs
===================================================================
--- /trunk/sources/HeuristicLab.Optimization/3.3/MetaOptimizers/Experiment.cs	(revision 15451)
+++ /trunk/sources/HeuristicLab.Optimization/3.3/MetaOptimizers/Experiment.cs	(revision 15452)
@@ -122,5 +122,14 @@
     private bool experimentStopped = false;
 
-    private readonly ManualResetEventSlim allOptimizerFinished = new ManualResetEventSlim(false); // this indicates that all started optimizers have been paused or stopped
+    // track already started optimizers (.StartAsync does not set the executionstate immediately)
+    // and to avoid restarting optimizers that were manually paused/stopped by the user
+    private readonly IDictionary<IOptimizer, Task> startedOptimizers = new Dictionary<IOptimizer, Task>();
+    private IEnumerable<IOptimizer> StartableOptimizers {
+      get {
+        return Optimizers
+          .Where(x => x.ExecutionState == ExecutionState.Prepared || x.ExecutionState == ExecutionState.Paused)
+          .Where(o => !startedOptimizers.ContainsKey(o));  // all startable optimizers that were not startet yet
+      }
+    }
 
     public Experiment()
@@ -205,30 +214,26 @@
         throw new InvalidOperationException(string.Format("Start not allowed in execution state \"{0}\".", ExecutionState));
 
-      // Multiple enumerations of runnableOptimizers is done on purpose to get the latest list of runnnable optimizers lazily
-      var runnableOptimizers = Optimizers.Where(x => x.ExecutionState == ExecutionState.Prepared || x.ExecutionState == ExecutionState.Paused);
-      if (!runnableOptimizers.Any()) return;
+      startedOptimizers.Clear();
+      if (!StartableOptimizers.Any()) return;
 
       experimentStarted = true;
       experimentStopped = false;
 
-      var startedOptimizers = new Dictionary<IOptimizer, Task>(); // track already started optimizers (.StartAsync does not set the executionstate immediately)
       using (var availableWorkers = new SemaphoreSlim(NumberOfWorkers, NumberOfWorkers)) {
-        while (runnableOptimizers.Any(o => !startedOptimizers.ContainsKey(o))) {
+        while (StartableOptimizers.Any()) {
           try {
             availableWorkers.Wait(cancellationToken);
-            if (experimentStopped || !experimentStarted) break;
-            var optimizer = runnableOptimizers.FirstOrDefault(o => !startedOptimizers.ContainsKey(o));
-            if (optimizer != null) {
-              var startedTask = optimizer.StartAsync(cancellationToken).ContinueWith(async t => {
-                availableWorkers.Release(); // is guaranteed to be not disposed yet because Task.WaitAll blocks before the end of the using
-                await t; // trigger a potential exception on the optimizerTask
-              });
-              startedOptimizers.Add(optimizer, startedTask.Unwrap()); // unwrap task because lambda of .ContinueWith is async
-            }
+            var optimizer = StartableOptimizers.FirstOrDefault();
+            if (experimentStopped || !experimentStarted || optimizer == null) break;
+
+            var startedTask = optimizer.StartAsync(cancellationToken).ContinueWith(async t => {
+              availableWorkers.Release(); // is guaranteed to be not disposed yet because Task.WaitAll blocks before the end of the using
+              await t; // trigger a potential exception on the optimizerTask
+            });
+            startedOptimizers.Add(optimizer, startedTask.Unwrap()); // unwrap task because lambda of .ContinueWith is async
           } catch (InvalidOperationException) { } catch (OperationCanceledException) { }
         }
 
         Task.WaitAll(startedOptimizers.Values.ToArray()); // retreive exeptions of the asyncrounously started optimizer
-        allOptimizerFinished.Wait();
       }
     }
@@ -297,5 +302,4 @@
     private void OnPaused() {
       ExecutionState = ExecutionState.Paused;
-      allOptimizerFinished.Set();
       EventHandler handler = Paused;
       if (handler != null) handler(this, EventArgs.Empty);
@@ -304,5 +308,4 @@
     private void OnStopped() {
       ExecutionState = ExecutionState.Stopped;
-      allOptimizerFinished.Set();
       EventHandler handler = Stopped;
       if (handler != null) handler(this, EventArgs.Empty);
@@ -400,14 +403,8 @@
     }
     private void optimizer_Paused(object sender, EventArgs e) {
-      lock (locker) {
-        if (Optimizers.All(x => x.ExecutionState != ExecutionState.Started)) {
-          OnPaused();
-        }
-        experimentStarted = false;
-      }
+      UpdateExecutionState();
     }
     private void optimizer_Prepared(object sender, EventArgs e) {
-      lock (locker)
-        if (Optimizers.All(x => x.ExecutionState == ExecutionState.Prepared)) OnPrepared();
+      UpdateExecutionState();
     }
     private void optimizer_Started(object sender, EventArgs e) {
@@ -416,17 +413,42 @@
     }
     private void optimizer_Stopped(object sender, EventArgs e) {
+      UpdateExecutionState();
+    }
+    private void UpdateExecutionState() {
+      // Execution states of the Experiment are determined using the following _basic_ rules:
+      //   if any Optimizer is Started      => Experiment is Started  (2. if)
+      //   if any Optimizer is Paused       => Experiment is Paused   (3. if)
+      //   if any Optimizer is Prepared     => Experiment is Prepared (5. if)
+      //   else (all Optimizer are Stopped) => Experiment is Stopped  (6. if)
+      // Additional there are two extra rules:
+      //   if the Experiment is running and there are still optimizers that can be started => keep the Experiment Running (1. if)
+      //   if experiment-stop is pending: Stop Experiment even if there are still Prepared Optimizer               (4. if)
+
       lock (locker) {
-        if (experimentStopped) {
-          if (Optimizers.All(x => (x.ExecutionState == ExecutionState.Stopped) || (x.ExecutionState == ExecutionState.Prepared))) OnStopped();
-        } else {
-          if (experimentStarted && Optimizers.Any(x => (x.ExecutionState == ExecutionState.Prepared) || (x.ExecutionState == ExecutionState.Paused))) return;
-          else if (Optimizers.All(x => x.ExecutionState == ExecutionState.Stopped)) {
-            OnStopped();
-          } else if (Optimizers.Any(x => (x.ExecutionState == ExecutionState.Prepared) || (x.ExecutionState == ExecutionState.Paused)) && Optimizers.All(o => o.ExecutionState != ExecutionState.Started)) {
-            OnPaused();
-          }
-        }
-      }
-    }
+        // 1. experiment is running & further startable optimizers are available => continue executing
+        if (experimentStarted && StartableOptimizers.Any()) return;
+
+        // 2. any optimizer is running => continue executing
+        else if (Optimizers.Any(x => x.ExecutionState == ExecutionState.Started))
+          return;
+
+        // 3. any optimizer is paused => experiment paused
+        else if (Optimizers.Any(x => x.ExecutionState == ExecutionState.Paused))
+          OnPaused();
+
+        // 4. stop pending & all optimizers either stopped or prepared => experiment stopped
+        else if (experimentStopped)
+          OnStopped();
+
+        // 5. any optimizer prepared => experiment prepared
+        else if (Optimizers.Any(x => x.ExecutionState == ExecutionState.Prepared))
+          OnPrepared();
+
+        // 6. (else) all optimizers stopped
+        else
+          OnStopped();
+      }
+    }
+
     private void optimizer_Runs_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRun> e) {
       lock (runsLocker) {
