Index: stable/HeuristicLab.Optimization/3.3/MetaOptimizers/TimeLimitRun.cs
===================================================================
--- stable/HeuristicLab.Optimization/3.3/MetaOptimizers/TimeLimitRun.cs	(revision 17112)
+++ stable/HeuristicLab.Optimization/3.3/MetaOptimizers/TimeLimitRun.cs	(revision 17115)
@@ -27,9 +27,9 @@
 using System.Threading;
 using System.Threading.Tasks;
+using HEAL.Attic;
 using HeuristicLab.Collections;
 using HeuristicLab.Common;
 using HeuristicLab.Common.Resources;
 using HeuristicLab.Core;
-using HEAL.Attic;
 
 namespace HeuristicLab.Optimization {
@@ -62,5 +62,5 @@
         if (maximumExecutionTime == value) return;
         maximumExecutionTime = value;
-        OnPropertyChanged("MaximumExecutionTime");
+        OnPropertyChanged(nameof(MaximumExecutionTime));
       }
     }
@@ -77,5 +77,5 @@
         snapshotTimes.Sort();
         FindNextSnapshotTimeIndex(ExecutionTime);
-        OnPropertyChanged("SnapshotTimes");
+        OnPropertyChanged(nameof(SnapshotTimes));
       }
     }
@@ -89,5 +89,5 @@
         if (storeAlgorithmInEachSnapshot == value) return;
         storeAlgorithmInEachSnapshot = value;
-        OnPropertyChanged("StoreAlgorithmInEachSnapshot");
+        OnPropertyChanged(nameof(StoreAlgorithmInEachSnapshot));
       }
     }
@@ -100,11 +100,19 @@
         if (snapshots == value) return;
         snapshots = value;
-        OnPropertyChanged("Snapshots");
+        OnPropertyChanged(nameof(Snapshots));
       }
     }
 
     #region Inherited Properties
+    [Storable]
+    private ExecutionState executionState;
     public ExecutionState ExecutionState {
-      get { return (Algorithm != null) ? Algorithm.ExecutionState : ExecutionState.Stopped; }
+      get { return executionState; }
+      private set {
+        if (executionState == value) return;
+        executionState = value;
+        OnExecutionStateChanged();
+        OnPropertyChanged(nameof(ExecutionState));
+      }
     }
 
@@ -119,11 +127,17 @@
       set {
         if (algorithm == value) return;
+        if (ExecutionState == ExecutionState.Started || ExecutionState == ExecutionState.Paused)
+          throw new InvalidOperationException("Cannot change algorithm while the TimeLimitRun is running or paused.");
         if (algorithm != null) DeregisterAlgorithmEvents();
         algorithm = value;
+        if (algorithm != null) RegisterAlgorithmEvents();
+        OnPropertyChanged(nameof(Algorithm));
+        OnPropertyChanged(nameof(NestedOptimizers));
         if (algorithm != null) {
-          RegisterAlgorithmEvents();
-        }
-        OnPropertyChanged("Algorithm");
-        Prepare();
+          if (algorithm.ExecutionState == ExecutionState.Started || algorithm.ExecutionState == ExecutionState.Paused)
+            throw new InvalidOperationException("Cannot assign a running or paused algorithm to a TimeLimitRun.");
+          Prepare();
+          if (algorithm.ExecutionState == ExecutionState.Stopped) OnStopped();
+        } else OnStopped();
       }
     }
@@ -137,5 +151,5 @@
         if (runs == value) return;
         runs = value;
-        OnPropertyChanged("Runs");
+        OnPropertyChanged(nameof(Runs));
       }
     }
@@ -160,4 +174,5 @@
       snapshots = cloner.Clone(original.snapshots);
       storeAlgorithmInEachSnapshot = original.storeAlgorithmInEachSnapshot;
+      executionState = original.executionState;
       algorithm = cloner.Clone(original.algorithm);
       runs = cloner.Clone(original.runs);
@@ -169,4 +184,5 @@
       name = ItemName;
       description = ItemDescription;
+      executionState = ExecutionState.Stopped;
       maximumExecutionTime = TimeSpan.FromMinutes(.5);
       snapshotTimes = new ObservableList<TimeSpan>(new[] {
@@ -182,4 +198,5 @@
       : base(name) {
       description = ItemDescription;
+      executionState = ExecutionState.Stopped;
       maximumExecutionTime = TimeSpan.FromMinutes(.5);
       snapshotTimes = new ObservableList<TimeSpan>(new[] {
@@ -194,4 +211,5 @@
     public TimeLimitRun(string name, string description)
       : base(name, description) {
+      executionState = ExecutionState.Stopped;
       maximumExecutionTime = TimeSpan.FromMinutes(.5);
       snapshotTimes = new ObservableList<TimeSpan>(new[] {
@@ -213,4 +231,10 @@
     private void AfterDeserialization() {
       Initialize();
+      // BackwardsCompatibility3.3
+      #region Backwards compatible code, remove with 3.4
+      if (Algorithm != null && executionState != Algorithm.ExecutionState) {
+        executionState = Algorithm.ExecutionState;
+      } else if (Algorithm == null) executionState = ExecutionState.Stopped;
+      #endregion
     }
 
@@ -238,4 +262,5 @@
     }
     public void Prepare(bool clearRuns) {
+      if (Algorithm == null) return;
       Algorithm.Prepare(clearRuns);
     }
@@ -282,4 +307,5 @@
     public event EventHandler Prepared;
     private void OnPrepared() {
+      ExecutionState = ExecutionState.Prepared;
       var handler = Prepared;
       if (handler != null) handler(this, EventArgs.Empty);
@@ -287,4 +313,5 @@
     public event EventHandler Started;
     private void OnStarted() {
+      ExecutionState = ExecutionState.Started;
       var handler = Started;
       if (handler != null) handler(this, EventArgs.Empty);
@@ -292,4 +319,5 @@
     public event EventHandler Paused;
     private void OnPaused() {
+      ExecutionState = ExecutionState.Paused;
       var handler = Paused;
       if (handler != null) handler(this, EventArgs.Empty);
@@ -297,4 +325,5 @@
     public event EventHandler Stopped;
     private void OnStopped() {
+      ExecutionState = ExecutionState.Stopped;
       var handler = Stopped;
       if (handler != null) handler(this, EventArgs.Empty);
@@ -302,4 +331,5 @@
     public event EventHandler<EventArgs<Exception>> ExceptionOccurred;
     private void OnExceptionOccurred(Exception exception) {
+      ExecutionState = ExecutionState.Paused;
       var handler = ExceptionOccurred;
       if (handler != null) handler(this, new EventArgs<Exception>(exception));
@@ -311,5 +341,4 @@
       algorithm.ExceptionOccurred += Algorithm_ExceptionOccurred;
       algorithm.ExecutionTimeChanged += Algorithm_ExecutionTimeChanged;
-      algorithm.ExecutionStateChanged += Algorithm_ExecutionStateChanged;
       algorithm.Paused += Algorithm_Paused;
       algorithm.Prepared += Algorithm_Prepared;
@@ -320,5 +349,4 @@
       algorithm.ExceptionOccurred -= Algorithm_ExceptionOccurred;
       algorithm.ExecutionTimeChanged -= Algorithm_ExecutionTimeChanged;
-      algorithm.ExecutionStateChanged -= Algorithm_ExecutionStateChanged;
       algorithm.Paused -= Algorithm_Paused;
       algorithm.Prepared -= Algorithm_Prepared;
@@ -340,7 +368,4 @@
       }
       OnExecutionTimeChanged();
-    }
-    private void Algorithm_ExecutionStateChanged(object sender, EventArgs e) {
-      OnExecutionStateChanged();
     }
     private void Algorithm_Paused(object sender, EventArgs e) {
@@ -350,6 +375,5 @@
         MakeSnapshot();
         FindNextSnapshotTimeIndex(ExecutionTime);
-      }
-      OnPaused();
+      } else OnPaused();
       if (action == ExecutionState.Started) Algorithm.Start();
       else if (action == ExecutionState.Stopped) Algorithm.Stop();
@@ -361,14 +385,19 @@
     }
     private void Algorithm_Started(object sender, EventArgs e) {
-      OnStarted();
+      if (ExecutionState == ExecutionState.Prepared || ExecutionState == ExecutionState.Paused)
+        OnStarted();
+      if (ExecutionState == ExecutionState.Stopped)
+        throw new InvalidOperationException("Algorithm was started although TimeLimitRun was in state Stopped.");
+      // otherwise the algorithm was just started after being snapshotted
     }
     private void Algorithm_Stopped(object sender, EventArgs e) {
-      var cloner = new Cloner();
-      var algRun = cloner.Clone(Algorithm.Runs.Last());
-      var clonedSnapshots = cloner.Clone(snapshots);
-      algRun.Results.Add("TimeLimitRunSnapshots", clonedSnapshots);
-      Runs.Add(algRun);
-      Algorithm.Runs.Clear();
-      OnStopped();
+      try {
+        var cloner = new Cloner();
+        var algRun = cloner.Clone(Algorithm.Runs.Last());
+        var clonedSnapshots = cloner.Clone(snapshots);
+        algRun.Results.Add("TimeLimitRunSnapshots", clonedSnapshots);
+        Runs.Add(algRun);
+        Algorithm.Runs.Clear();
+      } finally { OnStopped(); }
     }
     #endregion
@@ -379,5 +408,5 @@
       while (index < snapshotTimes.Count && snapshotTimes[index] <= reference) {
         index++;
-      };
+      }
       snapshotTimesIndex = index;
     }
