Index: trunk/sources/HeuristicLab.Optimization/3.3/Algorithms/BasicAlgorithm.cs
===================================================================
--- trunk/sources/HeuristicLab.Optimization/3.3/Algorithms/BasicAlgorithm.cs	(revision 15367)
+++ trunk/sources/HeuristicLab.Optimization/3.3/Algorithms/BasicAlgorithm.cs	(revision 15408)
@@ -80,11 +80,8 @@
       try {
         Run((object)cancellationTokenSource.Token);
-      }
-      catch (OperationCanceledException) {
-      }
-      catch (AggregateException ae) {
+      } catch (OperationCanceledException) {
+      } catch (AggregateException ae) {
         ae.FlattenAndHandle(new[] { typeof(OperationCanceledException) }, e => OnExceptionOccurred(e));
-      }
-      catch (Exception e) {
+      } catch (Exception e) {
         OnExceptionOccurred(e);
       }
@@ -104,5 +101,5 @@
       base.Pause();
       pausePending = true;
-      CancellationTokenSource.Cancel();
+      CancellationTokenSource?.Cancel();
     }
 
@@ -112,5 +109,5 @@
       base.Stop();
       if (ExecutionState == ExecutionState.Paused) OnStopped();
-      else CancellationTokenSource.Cancel();
+      else CancellationTokenSource?.Cancel();
     }
 
@@ -127,6 +124,5 @@
         initialized = true;
         Run(cancellationToken);
-      }
-      finally {
+      } finally {
         timer.Elapsed -= new System.Timers.ElapsedEventHandler(timer_Elapsed);
         timer.Stop();
Index: trunk/sources/HeuristicLab.Optimization/3.3/MetaOptimizers/BatchRun.cs
===================================================================
--- trunk/sources/HeuristicLab.Optimization/3.3/MetaOptimizers/BatchRun.cs	(revision 15367)
+++ trunk/sources/HeuristicLab.Optimization/3.3/MetaOptimizers/BatchRun.cs	(revision 15408)
@@ -258,4 +258,5 @@
         if (ExecutionState == ExecutionState.Paused || ExecutionState == ExecutionState.Stopped) break;
         Optimizer.Prepare();
+        if (ExecutionState == ExecutionState.Paused || ExecutionState == ExecutionState.Stopped) break;
       }
     }
@@ -271,5 +272,5 @@
       if (Optimizer.ExecutionState != ExecutionState.Started) return;
       // a race-condition may occur when the optimizer has changed the state by itself in the meantime
-      try { Optimizer.Pause(); } catch (InvalidOperationException) { }
+      try { Optimizer.Pause(); } catch (InvalidOperationException) { } catch (NotSupportedException) { }
     }
     public void Stop() {
Index: trunk/sources/HeuristicLab.Optimization/3.3/MetaOptimizers/Experiment.cs
===================================================================
--- trunk/sources/HeuristicLab.Optimization/3.3/MetaOptimizers/Experiment.cs	(revision 15367)
+++ trunk/sources/HeuristicLab.Optimization/3.3/MetaOptimizers/Experiment.cs	(revision 15408)
@@ -97,4 +97,14 @@
     }
 
+    [Storable]
+    private int numberOfWorkers = 1;
+    public int NumberOfWorkers {
+      get { return numberOfWorkers; }
+      set {
+        if (value < 1) throw new ArgumentException("Number of Workers must not be lower than one.");
+        numberOfWorkers = value;
+      }
+    }
+
     public IEnumerable<IOptimizer> NestedOptimizers {
       get {
@@ -111,4 +121,5 @@
     private bool experimentStarted = false;
     private bool experimentStopped = false;
+
     private readonly ManualResetEventSlim allOptimizerFinished = new ManualResetEventSlim(false); // this indicates that all started optimizers have been paused or stopped
 
@@ -155,4 +166,5 @@
       experimentStarted = original.experimentStarted;
       experimentStopped = original.experimentStopped;
+      numberOfWorkers = original.numberOfWorkers;
       Initialize();
     }
@@ -192,16 +204,32 @@
       if ((ExecutionState != ExecutionState.Prepared) && (ExecutionState != ExecutionState.Paused))
         throw new InvalidOperationException(string.Format("Start not allowed in execution state \"{0}\".", ExecutionState));
-      if (!Optimizers.Any(x => x.ExecutionState == ExecutionState.Prepared || x.ExecutionState == ExecutionState.Paused)) return;
+
+      // 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;
 
       experimentStarted = true;
       experimentStopped = false;
-      allOptimizerFinished.Reset();
-      IOptimizer optimizer;
-      while ((optimizer = Optimizers.FirstOrDefault(x => x.ExecutionState == ExecutionState.Prepared || x.ExecutionState == ExecutionState.Paused)) != null) {
-        // a race-condition may occur when the optimizer has changed the state by itself in the meantime
-        try { optimizer.Start(cancellationToken); } catch (InvalidOperationException) { }
-        if (ExecutionState == ExecutionState.Paused || ExecutionState == ExecutionState.Stopped) break;
-      }
-      allOptimizerFinished.Wait();
+
+      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))) {
+          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
+            }
+          } catch (InvalidOperationException) { } catch (OperationCanceledException) { }
+        }
+
+        Task.WaitAll(startedOptimizers.Values.ToArray()); // retreive exeptions of the asyncrounously started optimizer
+        allOptimizerFinished.Wait();
+      }
     }
     public async Task StartAsync() { await StartAsync(CancellationToken.None); }
@@ -218,5 +246,5 @@
       foreach (IOptimizer optimizer in Optimizers.Where(x => x.ExecutionState == ExecutionState.Started)) {
         // a race-condition may occur when the optimizer has changed the state by itself in the meantime
-        try { optimizer.Pause(); } catch (InvalidOperationException) { }
+        try { optimizer.Pause(); } catch (InvalidOperationException) { } catch (NotSupportedException) { }
       }
     }
@@ -372,6 +400,10 @@
     }
     private void optimizer_Paused(object sender, EventArgs e) {
-      lock (locker)
-        if (Optimizers.All(x => x.ExecutionState != ExecutionState.Started)) OnPaused();
+      lock (locker) {
+        if (Optimizers.All(x => x.ExecutionState != ExecutionState.Started)) {
+          OnPaused();
+        }
+        experimentStarted = false;
+      }
     }
     private void optimizer_Prepared(object sender, EventArgs e) {
@@ -389,6 +421,9 @@
         } 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();
+          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();
+          }
         }
       }
