Index: branches/ScatterSearch (trunk integration)/HeuristicLab.Optimization/3.3/BatchRun.cs
===================================================================
--- branches/ScatterSearch (trunk integration)/HeuristicLab.Optimization/3.3/BatchRun.cs	(revision 7787)
+++ branches/ScatterSearch (trunk integration)/HeuristicLab.Optimization/3.3/BatchRun.cs	(revision 8331)
@@ -30,4 +30,6 @@
 
 namespace HeuristicLab.Optimization {
+  internal enum BatchRunAction { None, Prepare, Start, Pause, Stop };
+
   /// <summary>
   /// A run in which an optimizer is executed a given number of times.
@@ -79,4 +81,7 @@
       }
     }
+
+    [Storable]
+    private TimeSpan runsExecutionTime;
 
     [Storable]
@@ -150,7 +155,5 @@
     }
 
-    private bool batchRunStarted = false;
-    private bool batchRunPaused = false;
-    private bool batchRunStopped = false;
+    private BatchRunAction batchRunAction = BatchRunAction.None;
 
     public BatchRun()
@@ -160,4 +163,5 @@
       executionState = ExecutionState.Stopped;
       executionTime = TimeSpan.Zero;
+      runsExecutionTime = TimeSpan.Zero;
       repetitions = 10;
       repetitionsCounter = 0;
@@ -169,4 +173,5 @@
       executionState = ExecutionState.Stopped;
       executionTime = TimeSpan.Zero;
+      runsExecutionTime = TimeSpan.Zero;
       repetitions = 10;
       repetitionsCounter = 0;
@@ -177,4 +182,5 @@
       executionState = ExecutionState.Stopped;
       executionTime = TimeSpan.Zero;
+      runsExecutionTime = TimeSpan.Zero;
       repetitions = 10;
       repetitionsCounter = 0;
@@ -192,11 +198,10 @@
       executionState = original.executionState;
       executionTime = original.executionTime;
+      runsExecutionTime = original.runsExecutionTime;
       optimizer = cloner.Clone(original.optimizer);
       repetitions = original.repetitions;
       repetitionsCounter = original.repetitionsCounter;
       runs = cloner.Clone(original.runs);
-      batchRunStarted = original.batchRunStarted;
-      batchRunPaused = original.batchRunPaused;
-      batchRunStopped = original.batchRunStopped;
+      batchRunAction = original.batchRunAction;
       Initialize();
     }
@@ -218,7 +223,10 @@
         throw new InvalidOperationException(string.Format("Prepare not allowed in execution state \"{0}\".", ExecutionState));
       if (Optimizer != null) {
+        ExecutionTime = TimeSpan.Zero;
         repetitionsCounter = 0;
         if (clearRuns) runs.Clear();
-        Optimizer.Prepare(clearRuns);
+        batchRunAction = BatchRunAction.Prepare;
+        // a race-condition may occur when the optimizer has changed the state by itself in the meantime
+        try { Optimizer.Prepare(clearRuns); } catch (InvalidOperationException) { }
       } else {
         ExecutionState = ExecutionState.Stopped;
@@ -229,10 +237,8 @@
         throw new InvalidOperationException(string.Format("Start not allowed in execution state \"{0}\".", ExecutionState));
       if (Optimizer == null) return;
-
-      batchRunStarted = true;
-      batchRunPaused = false;
-      batchRunStopped = false;
+      batchRunAction = BatchRunAction.Start;
       if (Optimizer.ExecutionState == ExecutionState.Stopped) Optimizer.Prepare();
-      Optimizer.Start();
+      // a race-condition may occur when the optimizer has changed the state by itself in the meantime
+      try { Optimizer.Start(); } catch (InvalidOperationException) { }
     }
     public void Pause() {
@@ -240,10 +246,8 @@
         throw new InvalidOperationException(string.Format("Pause not allowed in execution state \"{0}\".", ExecutionState));
       if (Optimizer == null) return;
+      batchRunAction = BatchRunAction.Pause;
       if (Optimizer.ExecutionState != ExecutionState.Started) return;
-
-      batchRunStarted = false;
-      batchRunPaused = true;
-      batchRunStopped = false;
-      Optimizer.Pause();
+      // a race-condition may occur when the optimizer has changed the state by itself in the meantime
+      try { Optimizer.Pause(); } catch (InvalidOperationException) { }
     }
     public void Stop() {
@@ -251,9 +255,11 @@
         throw new InvalidOperationException(string.Format("Stop not allowed in execution state \"{0}\".", ExecutionState));
       if (Optimizer == null) return;
-      if (Optimizer.ExecutionState != ExecutionState.Started && Optimizer.ExecutionState != ExecutionState.Paused) return;
-      batchRunStarted = false;
-      batchRunPaused = false;
-      batchRunStopped = true;
-      Optimizer.Stop();
+      batchRunAction = BatchRunAction.Stop;
+      if (Optimizer.ExecutionState != ExecutionState.Started && Optimizer.ExecutionState != ExecutionState.Paused) {
+        OnStopped();
+        return;
+      }
+      // a race-condition may occur when the optimizer has changed the state by itself in the meantime
+      try { Optimizer.Stop(); } catch (InvalidOperationException) { }
     }
 
@@ -281,4 +287,5 @@
     public event EventHandler Prepared;
     private void OnPrepared() {
+      batchRunAction = BatchRunAction.None;
       ExecutionState = ExecutionState.Prepared;
       EventHandler handler = Prepared;
@@ -287,4 +294,5 @@
     public event EventHandler Started;
     private void OnStarted() {
+      // no reset of BatchRunAction.Started, because we need to differ which of the two was started by the user
       ExecutionState = ExecutionState.Started;
       EventHandler handler = Started;
@@ -293,4 +301,5 @@
     public event EventHandler Paused;
     private void OnPaused() {
+      batchRunAction = BatchRunAction.None;
       ExecutionState = ExecutionState.Paused;
       EventHandler handler = Paused;
@@ -299,4 +308,5 @@
     public event EventHandler Stopped;
     private void OnStopped() {
+      batchRunAction = BatchRunAction.None;
       ExecutionState = ExecutionState.Stopped;
       EventHandler handler = Stopped;
@@ -343,5 +353,8 @@
     }
     private void Optimizer_Prepared(object sender, EventArgs e) {
-      if (ExecutionState == ExecutionState.Stopped || !batchRunStarted) {
+      if (batchRunAction == BatchRunAction.Prepare || ExecutionState == ExecutionState.Stopped) {
+        ExecutionTime = TimeSpan.Zero;
+        runsExecutionTime = TimeSpan.Zero;
+        repetitionsCounter = 0;
         OnPrepared();
       }
@@ -353,11 +366,16 @@
     private void Optimizer_Stopped(object sender, EventArgs e) {
       repetitionsCounter++;
-
-      if (batchRunStopped) OnStopped();
+      ExecutionTime += runsExecutionTime;
+      runsExecutionTime = TimeSpan.Zero;
+
+      if (batchRunAction == BatchRunAction.Stop) OnStopped();
       else if (repetitionsCounter >= repetitions) OnStopped();
-      else if (batchRunPaused) OnPaused();
-      else if (batchRunStarted) {
+      else if (batchRunAction == BatchRunAction.Pause) OnPaused();
+      else if (batchRunAction == BatchRunAction.Start) {
         Optimizer.Prepare();
         Optimizer.Start();
+      } else if (executionState == ExecutionState.Started) {
+        // if the batch run hasn't been started but the inner optimizer was run then pause
+        OnPaused();
       } else OnStopped();
     }
@@ -385,10 +403,4 @@
     }
     private void Runs_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRun> e) {
-      foreach (IRun run in e.OldItems) {
-        IItem item;
-        run.Results.TryGetValue("Execution Time", out item);
-        TimeSpanValue executionTime = item as TimeSpanValue;
-        if (executionTime != null) ExecutionTime -= executionTime.Value;
-      }
       if (Optimizer != null) Optimizer.Runs.RemoveRange(e.OldItems);
       foreach (IRun run in e.Items) {
@@ -404,14 +416,13 @@
         run.Results.TryGetValue("Execution Time", out item);
         TimeSpanValue executionTime = item as TimeSpanValue;
-        if (executionTime != null) ExecutionTime += executionTime.Value;
+        if (executionTime != null) {
+          if (Optimizer.ExecutionState == ExecutionState.Started)
+            runsExecutionTime += executionTime.Value;
+          else
+            ExecutionTime += executionTime.Value;
+        }
       }
     }
     private void Runs_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IRun> e) {
-      foreach (IRun run in e.Items) {
-        IItem item;
-        run.Results.TryGetValue("Execution Time", out item);
-        TimeSpanValue executionTime = item as TimeSpanValue;
-        if (executionTime != null) ExecutionTime -= executionTime.Value;
-      }
       if (Optimizer != null) Optimizer.Runs.RemoveRange(e.Items);
     }
