Index: branches/RuntimeOptimizer/HeuristicLab.Optimization.Views/3.3/HeuristicLab.Optimization.Views-3.3.csproj
===================================================================
--- branches/RuntimeOptimizer/HeuristicLab.Optimization.Views/3.3/HeuristicLab.Optimization.Views-3.3.csproj	(revision 8955)
+++ branches/RuntimeOptimizer/HeuristicLab.Optimization.Views/3.3/HeuristicLab.Optimization.Views-3.3.csproj	(revision 8956)
@@ -398,9 +398,4 @@
     </ProjectReference>
   </ItemGroup>
-  <ItemGroup>
-    <EmbeddedResource Include="TimeLimitRunView.resx">
-      <DependentUpon>TimeLimitRunView.cs</DependentUpon>
-    </EmbeddedResource>
-  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
Index: branches/RuntimeOptimizer/HeuristicLab.Optimization.Views/3.3/TimeLimitRunView.Designer.cs
===================================================================
--- branches/RuntimeOptimizer/HeuristicLab.Optimization.Views/3.3/TimeLimitRunView.Designer.cs	(revision 8955)
+++ branches/RuntimeOptimizer/HeuristicLab.Optimization.Views/3.3/TimeLimitRunView.Designer.cs	(revision 8956)
@@ -50,4 +50,5 @@
       this.runsView = new HeuristicLab.Optimization.Views.RunCollectionView();
       this.openFileDialog = new System.Windows.Forms.OpenFileDialog();
+      this.snapshotButton = new System.Windows.Forms.Button();
       ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
       this.tabControl.SuspendLayout();
@@ -109,5 +110,4 @@
       this.timeLimitTextBox.Size = new System.Drawing.Size(338, 20);
       this.timeLimitTextBox.TabIndex = 17;
-      this.timeLimitTextBox.Leave += new System.EventHandler(this.timeLimitTextBox_Leave);
       this.timeLimitTextBox.Validating += new System.ComponentModel.CancelEventHandler(this.timeLimitTextBox_Validating);
       // 
@@ -127,5 +127,5 @@
       this.snapShotsTextBox.Location = new System.Drawing.Point(69, 52);
       this.snapShotsTextBox.Name = "snapShotsTextBox";
-      this.snapShotsTextBox.Size = new System.Drawing.Size(148, 20);
+      this.snapShotsTextBox.Size = new System.Drawing.Size(142, 20);
       this.snapShotsTextBox.TabIndex = 17;
       // 
@@ -266,8 +266,19 @@
       this.openFileDialog.Title = "Open Optimizer";
       // 
+      // snapshotButton
+      // 
+      this.snapshotButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+      this.snapshotButton.Location = new System.Drawing.Point(120, 440);
+      this.snapshotButton.Name = "snapshotButton";
+      this.snapshotButton.Size = new System.Drawing.Size(24, 24);
+      this.snapshotButton.TabIndex = 20;
+      this.snapshotButton.Text = "Snapshot";
+      this.snapshotButton.UseVisualStyleBackColor = true;
+      this.snapshotButton.Click += new System.EventHandler(this.snapshotButton_Click);
+      // 
       // TimeLimitRunView
       // 
-      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
-      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
+      this.Controls.Add(this.snapshotButton);
       this.Controls.Add(this.tabControl);
       this.Controls.Add(this.timeLimitTextBox);
@@ -283,4 +294,5 @@
       this.Controls.SetChildIndex(this.timeLimitLabel, 0);
       this.Controls.SetChildIndex(this.timeLimitTextBox, 0);
+      this.Controls.SetChildIndex(this.tabControl, 0);
       this.Controls.SetChildIndex(this.nameLabel, 0);
       this.Controls.SetChildIndex(this.nameTextBox, 0);
@@ -292,5 +304,5 @@
       this.Controls.SetChildIndex(this.executionTimeTextBox, 0);
       this.Controls.SetChildIndex(this.startButton, 0);
-      this.Controls.SetChildIndex(this.tabControl, 0);
+      this.Controls.SetChildIndex(this.snapshotButton, 0);
       ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
       this.tabControl.ResumeLayout(false);
@@ -320,4 +332,5 @@
     private RunCollectionView runsView;
     private System.Windows.Forms.OpenFileDialog openFileDialog;
+    private System.Windows.Forms.Button snapshotButton;
   }
 }
Index: branches/RuntimeOptimizer/HeuristicLab.Optimization.Views/3.3/TimeLimitRunView.cs
===================================================================
--- branches/RuntimeOptimizer/HeuristicLab.Optimization.Views/3.3/TimeLimitRunView.cs	(revision 8955)
+++ branches/RuntimeOptimizer/HeuristicLab.Optimization.Views/3.3/TimeLimitRunView.cs	(revision 8956)
@@ -25,4 +25,5 @@
 using System.Windows.Forms;
 using HeuristicLab.Common;
+using HeuristicLab.Common.Resources;
 using HeuristicLab.Core;
 using HeuristicLab.Core.Views;
@@ -45,4 +46,6 @@
     public TimeLimitRunView() {
       InitializeComponent();
+      snapshotButton.Text = String.Empty;
+      snapshotButton.Image = VSImageLibrary.Breakpoint;
     }
 
@@ -69,6 +72,5 @@
       try {
         if (Content == null) {
-          timeLimitTextBox.Tag = TimeSpan.FromSeconds(60);
-          timeLimitTextBox.Text = FormatTimeSpan((TimeSpan)timeLimitTextBox.Tag);
+          timeLimitTextBox.Text = FormatTimeSpan(TimeSpan.FromSeconds(60));
           snapShotsTextBox.Text = String.Empty;
           storeAlgorithmInEachSnapshotCheckBox.Checked = false;
@@ -77,5 +79,4 @@
           runsView.Content = null;
         } else {
-          timeLimitTextBox.Tag = Content.MaximumExecutionTime;
           timeLimitTextBox.Text = FormatTimeSpan(Content.MaximumExecutionTime);
           snapShotsTextBox.Text = String.Join(" ; ", Content.SnapshotTimes);
@@ -87,4 +88,5 @@
       } finally { SuppressEvents = false; }
     }
+
     protected override void SetEnabledStateOfControls() {
       base.SetEnabledStateOfControls();
@@ -99,4 +101,9 @@
     }
 
+    protected override void SetEnabledStateOfExecutableButtons() {
+      base.SetEnabledStateOfExecutableButtons();
+      snapshotButton.Enabled = Content != null && (Content.ExecutionState == ExecutionState.Started || Content.ExecutionState == ExecutionState.Paused);
+    }
+
     protected override void OnClosed(FormClosedEventArgs e) {
       if ((Content != null) && (Content.ExecutionState == ExecutionState.Started)) {
@@ -151,12 +158,4 @@
 
     #region Control events
-    private void timeLimitTextBox_Leave(object sender, EventArgs e) {
-      if (SuppressEvents) return;
-      SuppressEvents = true;
-      try {
-        timeLimitTextBox.Text = FormatTimeSpan((TimeSpan)timeLimitTextBox.Tag);
-      } finally { SuppressEvents = false; }
-    }
-
     private void timeLimitTextBox_Validating(object sender, CancelEventArgs e) {
       if (SuppressEvents) return;
@@ -179,5 +178,5 @@
           ts = GetTimeSpanFromFormat(value, text.Substring(length - 1, text.Length - (length - 1)).TrimStart());
         } else ts = TimeSpan.FromSeconds(value);
-        timeLimitTextBox.Tag = ts;
+        Content.MaximumExecutionTime = ts;
         e.Cancel = false;
         errorProvider.SetError(timeLimitTextBox, String.Empty);
@@ -252,4 +251,8 @@
       }
     }
+
+    private void snapshotButton_Click(object sender, EventArgs e) {
+      Content.Snapshot();
+    }
     #endregion
     #endregion
Index: branches/RuntimeOptimizer/HeuristicLab.Optimization.Views/3.3/TimeLimitRunView.resx
===================================================================
--- branches/RuntimeOptimizer/HeuristicLab.Optimization.Views/3.3/TimeLimitRunView.resx	(revision 8955)
+++ 	(revision )
@@ -1,162 +1,0 @@
-﻿<?xml version="1.0" encoding="utf-8"?>
-<root>
-  <!-- 
-    Microsoft ResX Schema 
-    
-    Version 2.0
-    
-    The primary goals of this format is to allow a simple XML format 
-    that is mostly human readable. The generation and parsing of the 
-    various data types are done through the TypeConverter classes 
-    associated with the data types.
-    
-    Example:
-    
-    ... ado.net/XML headers & schema ...
-    <resheader name="resmimetype">text/microsoft-resx</resheader>
-    <resheader name="version">2.0</resheader>
-    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
-    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
-    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
-    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
-    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
-        <value>[base64 mime encoded serialized .NET Framework object]</value>
-    </data>
-    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
-        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
-        <comment>This is a comment</comment>
-    </data>
-                
-    There are any number of "resheader" rows that contain simple 
-    name/value pairs.
-    
-    Each data row contains a name, and value. The row also contains a 
-    type or mimetype. Type corresponds to a .NET class that support 
-    text/value conversion through the TypeConverter architecture. 
-    Classes that don't support this are serialized and stored with the 
-    mimetype set.
-    
-    The mimetype is used for serialized objects, and tells the 
-    ResXResourceReader how to depersist the object. This is currently not 
-    extensible. For a given mimetype the value must be set accordingly:
-    
-    Note - application/x-microsoft.net.object.binary.base64 is the format 
-    that the ResXResourceWriter will generate, however the reader can 
-    read any of the formats listed below.
-    
-    mimetype: application/x-microsoft.net.object.binary.base64
-    value   : The object must be serialized with 
-            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
-            : and then encoded with base64 encoding.
-    
-    mimetype: application/x-microsoft.net.object.soap.base64
-    value   : The object must be serialized with 
-            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
-            : and then encoded with base64 encoding.
-
-    mimetype: application/x-microsoft.net.object.bytearray.base64
-    value   : The object must be serialized into a byte array 
-            : using a System.ComponentModel.TypeConverter
-            : and then encoded with base64 encoding.
-    -->
-  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
-    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
-    <xsd:element name="root" msdata:IsDataSet="true">
-      <xsd:complexType>
-        <xsd:choice maxOccurs="unbounded">
-          <xsd:element name="metadata">
-            <xsd:complexType>
-              <xsd:sequence>
-                <xsd:element name="value" type="xsd:string" minOccurs="0" />
-              </xsd:sequence>
-              <xsd:attribute name="name" use="required" type="xsd:string" />
-              <xsd:attribute name="type" type="xsd:string" />
-              <xsd:attribute name="mimetype" type="xsd:string" />
-              <xsd:attribute ref="xml:space" />
-            </xsd:complexType>
-          </xsd:element>
-          <xsd:element name="assembly">
-            <xsd:complexType>
-              <xsd:attribute name="alias" type="xsd:string" />
-              <xsd:attribute name="name" type="xsd:string" />
-            </xsd:complexType>
-          </xsd:element>
-          <xsd:element name="data">
-            <xsd:complexType>
-              <xsd:sequence>
-                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
-                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
-              </xsd:sequence>
-              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
-              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
-              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
-              <xsd:attribute ref="xml:space" />
-            </xsd:complexType>
-          </xsd:element>
-          <xsd:element name="resheader">
-            <xsd:complexType>
-              <xsd:sequence>
-                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
-              </xsd:sequence>
-              <xsd:attribute name="name" type="xsd:string" use="required" />
-            </xsd:complexType>
-          </xsd:element>
-        </xsd:choice>
-      </xsd:complexType>
-    </xsd:element>
-  </xsd:schema>
-  <resheader name="resmimetype">
-    <value>text/microsoft-resx</value>
-  </resheader>
-  <resheader name="version">
-    <value>2.0</value>
-  </resheader>
-  <resheader name="reader">
-    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
-  </resheader>
-  <resheader name="writer">
-    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
-  </resheader>
-  <metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
-    <value>17, 17</value>
-  </metadata>
-  <metadata name="errorProvider.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
-    <value>107, 17</value>
-  </metadata>
-  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
-  <data name="openAlgorithmButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
-    <value>
-        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
-        YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAALDAAA
-        CwwBP0AiyAAAAn9JREFUOE+lk2tI01EYxhf0oU8WqVEIRpaIBWJgSPUhROmippS3QkkTylsXDMW8ts3b
-        1G06daVibuqaOq0sxbBCKBSJ0PJCialZUFSKqaGSt1//TbIsww8deOBwznl+5zkv71kHiP5rGAFrKb1Q
-        5ypR6bmaVU6m2kCiXJv007Om2XgwJEaNT4QiyDi/GF9mKRVgsWkav+CYQkR1utwAQfypphqZ4l/JIhOL
-        jvtGKfCOyDMB6O/WMjNea9L3MT1zIxoM5QrqdWnS1SA+kUq8w1V4hhUgqq1QMj1WtcK88KmIud5oqsqy
-        qCzOQFMopSQvhRvyBApkcQLzV91E1docpr9ol29eFMz0J0Bv2Kr6C3CrVMa3jyWm2EZzc12OSQ8M2TTo
-        ZdytzMCgSUVfIqFcfY2bqiSKlQmoc+JNaUSVJRlMvsvHGHuoVUx9lZKFIQkMp63UW2FtMBH6YuBVFF01
-        /lwO9aoQadSpTAxkwXs596oVtD+ULx36/Qkvg6HDl/k2D2YeufCmwoELZ45MCIA9olKVmK+vJQy3JVOv
-        l7M4KIae8CVAV6hgPMV8uxczLYeZbDrIaN1eJBG2nHazyDN1cZEymdHueG7rcuh8KiTpixYA56AziMVn
-        J5h9coyp5kOM1TvxudqejvRNBHrY4GRnZmcCqLMT6GlJ4Y4uGwZS4IUQ97kfs62eTD12YbzBmRGDAx+0
-        u+iVmyMO24njbqvG5VbOz4yjtjyL3vuRdOSKltUuX0+LbAON0o3UJFmiibPi+pXtBLrvWHR2tHZfBuSm
-        xZIrPk9mfAiJlwKMleWsvxsnj+7H9YAD+xxssbexwnqbBVs2m7HV3GxlI631E9fa/wGRpaRpa3TTbQAA
-        AABJRU5ErkJggg==
-</value>
-  </data>
-  <data name="newAlgorithmButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
-    <value>
-        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
-        YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAALDAAA
-        CwwBP0AiyAAAAaJJREFUOE+Nkk1LAkEYx5egU9Sla9AX6NKhLlH3IujSoXtBn0EI+gB5qVBIKyIMtEDo
-        BUIhK6qDSUj4gqYloilmvqa5rrr/Zlx3dkU0B/48z87O/zfzPDMcAE7SOg8sB2AkqYdIXIoAK4LyX17X
-        HiVzYPhC0NBUB1yR6Jfy5lx59rQXRAKEhl6Y4YhMnXOSmUDywRlYHV5YbG6YLp1UW2pgEyBoSdARbdNP
-        OszSSQxEZnkO2D+7w/TCWhtEOoGfqyE5KmKnVf/HIHBLcn4SiI21oGQPkw32J68M0VKvBKgvulgJdEey
-        O+sJNhlg9/i6aZalAEpz98xwQADhAaWJ2GOAWr0BCpFBCoCeIjOxgdCIHlYCiI8DGQ1QMjKzKIooVwSk
-        MuUmYGp+lf5rlcDeArhD6wMzqZOqUEe2UEE0WegNMFgcHYB6Q0SxXEUiXcJbNNsboD+xdwAqfA3p3C8i
-        n3l4QuneAFqfetDG5X94xFJFBCIZuHzJ/gHqxoVjObwGv/DojvcPUDfO9/4NpyeBm+dofwD5vrvFrtco
-        3zFd8J/oO/gDpYIVhUFyWDsAAAAASUVORK5CYII=
-</value>
-  </data>
-  <metadata name="openFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
-    <value>230, 17</value>
-  </metadata>
-</root>
Index: branches/RuntimeOptimizer/HeuristicLab.Optimization/3.3/MetaOptimizers/TimeLimitRun.cs
===================================================================
--- branches/RuntimeOptimizer/HeuristicLab.Optimization/3.3/MetaOptimizers/TimeLimitRun.cs	(revision 8955)
+++ branches/RuntimeOptimizer/HeuristicLab.Optimization/3.3/MetaOptimizers/TimeLimitRun.cs	(revision 8956)
@@ -26,4 +26,5 @@
 using System.Linq;
 using System.Threading;
+using System.Threading.Tasks;
 using System.Timers;
 using HeuristicLab.Collections;
@@ -55,8 +56,10 @@
     #endregion
 
-    private readonly Timer snapTimer;
-    private readonly Timer runTimer;
+    private Timer snapTimer, runTimer;
+    private readonly ManualResetEvent algorithmStarted = new ManualResetEvent(false);
     private readonly ManualResetEvent algorithmPaused = new ManualResetEvent(false);
     private readonly ManualResetEvent algorithmStopped = new ManualResetEvent(false);
+    [Storable]
+    private bool snapshotTimesDirty;
 
     [Storable]
@@ -81,5 +84,5 @@
         if (snapshotTimes == value) return;
         snapshotTimes = value;
-        snapshotTimesIndex = 0;
+        snapshotTimesDirty = true;
         OnPropertyChanged("SnapshotTimes");
       }
@@ -124,14 +127,10 @@
       set {
         if (algorithm == value) return;
-        if (algorithm != null) {
-          DeregisterAlgorithmEvents();
-          var runs = algorithm.Runs;
-          algorithm = null; //necessary to avoid removing the runs from the old algorithm
-          Runs.RemoveRange(runs);
-        }
+        if (algorithm != null) DeregisterAlgorithmEvents();
         algorithm = value;
         if (algorithm != null) {
           RegisterAlgorithmEvents();
-          Runs.AddRange(algorithm.Runs);
+          if (algorithm.ExecutionState == ExecutionState.Started) algorithmStarted.Set();
+          else algorithmStarted.Reset();
           if (algorithm.ExecutionState == ExecutionState.Paused) algorithmPaused.Set();
           else algorithmPaused.Reset();
@@ -167,18 +166,5 @@
 
     [StorableConstructor]
-    private TimeLimitRun(bool deserializing)
-      : base(deserializing) {
-      // the timer will not be serialized
-      snapTimer = new Timer() {
-        AutoReset = false,
-        Enabled = false,
-        Interval = double.MaxValue
-      };
-      runTimer = new Timer() {
-        AutoReset = false,
-        Enabled = false,
-        Interval = double.MaxValue
-      };
-    }
+    private TimeLimitRun(bool deserializing) : base(deserializing) { }
     private TimeLimitRun(TimeLimitRun original, Cloner cloner)
       : base(original, cloner) {
@@ -186,18 +172,25 @@
       snapshotTimes = new ObservableList<double>(original.snapshotTimes);
       snapshotTimesIndex = original.snapshotTimesIndex;
-      snapTimer = new Timer() {
-        AutoReset = original.snapTimer.AutoReset,
-        Enabled = original.snapTimer.Enabled,
-        Interval = original.snapTimer.Interval
-      };
-      runTimer = new Timer() {
-        AutoReset = original.runTimer.AutoReset,
-        Enabled = original.runTimer.Enabled,
-        Interval = original.runTimer.Interval
-      };
       snapshots = cloner.Clone(original.snapshots);
+      snapshotTimesDirty = original.snapshotTimesDirty;
       storeAlgorithmInEachSnapshot = original.storeAlgorithmInEachSnapshot;
       algorithm = cloner.Clone(original.algorithm);
       runs = cloner.Clone(original.runs);
+
+      snapTimer = new Timer() {
+        AutoReset = original.snapTimer.AutoReset,
+        Interval = original.snapTimer.Interval
+      };
+      runTimer = new Timer() {
+        AutoReset = original.runTimer.AutoReset,
+        Interval = original.runTimer.Interval
+      };
+      if (original.algorithm != null && original.algorithm.ExecutionState == ExecutionState.Started)
+        algorithmStarted.Set();
+      if (original.algorithm != null && original.algorithm.ExecutionState == ExecutionState.Paused)
+        algorithmPaused.Set();
+      if (original.algorithm != null && original.algorithm.ExecutionState == ExecutionState.Stopped)
+        algorithmStopped.Set();
+
       Initialize();
     }
@@ -215,5 +208,5 @@
         AutoReset = false,
         Enabled = false,
-        Interval = snapshotTimes[snapshotTimesIndex]
+        Interval = 100
       };
       runTimer = new Timer() {
@@ -224,4 +217,5 @@
       snapshots = new RunCollection();
       Runs = new RunCollection { AlgorithmName = Name };
+      Initialize();
     }
     public TimeLimitRun(string name)
@@ -237,5 +231,5 @@
         AutoReset = false,
         Enabled = false,
-        Interval = snapshotTimes[snapshotTimesIndex]
+        Interval = 100
       };
       snapshots = new RunCollection();
@@ -246,4 +240,5 @@
       };
       Runs = new RunCollection { AlgorithmName = Name };
+      Initialize();
     }
     public TimeLimitRun(string name, string description)
@@ -258,5 +253,5 @@
         AutoReset = false,
         Enabled = false,
-        Interval = snapshotTimes[snapshotTimesIndex]
+        Interval = 100
       };
       snapshots = new RunCollection();
@@ -267,4 +262,5 @@
       };
       Runs = new RunCollection { AlgorithmName = Name };
+      Initialize();
     }
 
@@ -276,4 +272,24 @@
     [StorableHook(HookType.AfterDeserialization)]
     private void AfterDeserialization() {
+      // the timers will not be serialized
+      snapTimer = new Timer() {
+        AutoReset = false,
+        Enabled = false,
+        Interval = 100
+      };
+      runTimer = new Timer() {
+        AutoReset = false,
+        Enabled = false,
+        Interval = double.MaxValue
+      };
+      if (Algorithm != null && Algorithm.ExecutionState == ExecutionState.Started)
+        algorithmStarted.Set();
+      else algorithmStarted.Reset();
+      if (Algorithm != null && Algorithm.ExecutionState == ExecutionState.Paused)
+        algorithmPaused.Set();
+      else algorithmPaused.Reset();
+      if (Algorithm != null && Algorithm.ExecutionState == ExecutionState.Stopped)
+        algorithmStopped.Set();
+      else algorithmStopped.Reset();
       Initialize();
     }
@@ -281,46 +297,89 @@
     private void Initialize() {
       if (algorithm != null) RegisterAlgorithmEvents();
+      snapshotTimes.ItemsAdded += snapshotTimes_Changed;
+      snapshotTimes.ItemsMoved += snapshotTimes_Changed;
+      snapshotTimes.ItemsRemoved += snapshotTimes_Changed;
+      snapshotTimes.ItemsReplaced += snapshotTimes_Changed;
+      snapshotTimes.CollectionReset += snapshotTimes_Changed;
       snapTimer.Elapsed += snapshotTimer_Elapsed;
       runTimer.Elapsed += runTimer_Elapsed;
     }
 
-    private readonly object timerLock = new object();
+    private void snapshotTimes_Changed(object sender, EventArgs e) {
+      snapshotTimesDirty = true;
+    }
+
+    private readonly object snapshotLock = new object();
     private void snapshotTimer_Elapsed(object sender, ElapsedEventArgs e) {
-      lock (timerLock) {
-        runTimer.Stop();
-        if (Algorithm == null) return;
-        if (ExecutionState != ExecutionState.Started) return;
+      snapTimer.Stop();
+      lock (snapshotLock) {
+        try {
+          if (Algorithm == null) return;
+          if (ExecutionState != ExecutionState.Started) return;
+
+          var execTime = ExecutionTime;
+          if (snapshotTimesIndex < SnapshotTimes.Count &&
+              SnapshotTimes[snapshotTimesIndex] <= execTime.TotalMilliseconds) {
+            DoSnapshot();
+            snapshotTimesIndex++;
+            try {
+              Algorithm.Start();
+              algorithmStarted.WaitOne();
+            } catch (InvalidOperationException) { }
+          }
+        } catch { }
+        snapTimer.Start();
+      }
+    }
+
+    private void runTimer_Elapsed(object sender, ElapsedEventArgs e) {
+      snapTimer.Stop();
+      lock (snapshotLock) {
+        try {
+          Algorithm.Stop();
+          algorithmStopped.WaitOne();
+        } catch (InvalidOperationException) { }
+      }
+    }
+
+    private void FindNextSnapshotTimeIndex(TimeSpan reference) {
+      var index = 0;
+      while (index < snapshotTimes.Count && (snapshotTimes[index] - reference.TotalMilliseconds) <= 0) {
+        index++;
+      };
+      snapshotTimesIndex = index;
+    }
+
+    private void DoSnapshot() {
+      lock (snapshotLock) {
+        var wasPaused = Algorithm.ExecutionState == ExecutionState.Paused;
         var error = false;
-        try { Algorithm.Pause(); } catch (InvalidOperationException) { error = true; }
+        try {
+          Algorithm.Pause();
+          algorithmPaused.WaitOne();
+        } catch (InvalidOperationException) {
+          error = true;
+        }
         if (error && ExecutionState != ExecutionState.Paused) return; // Algorithm is either stopped or prepared
 
-        algorithmPaused.WaitOne();
         MakeSnapshot();
-        try { Algorithm.Start(); } catch (InvalidOperationException) { }
-      }
-    }
-
-    private void runTimer_Elapsed(object sender, ElapsedEventArgs e) {
-      lock (timerLock) {
-        runTimer.Stop();
-        snapTimer.Stop();
-        try { Algorithm.Stop(); } catch (InvalidOperationException) { }
-      }
-    }
-
-    private double? GetNextInterval(TimeSpan reference) {
-      double interval;
-      while ((interval = snapshotTimes[snapshotTimesIndex] - reference.TotalMilliseconds) <= 0) {
-        snapshotTimesIndex++;
-        if (snapshotTimesIndex >= snapshotTimes.Count) return null;
-      };
-      return interval;
+        if (!wasPaused) {
+          try {
+            Algorithm.Start();
+            algorithmStarted.WaitOne();
+          } catch (InvalidOperationException) { }
+        }
+      }
     }
 
     private void MakeSnapshot() {
-      string runName = ExecutionTime.ToString() + " " + algorithm.Name + " Snapshot";
+      string time = Math.Round(ExecutionTime.TotalSeconds, 1).ToString("0.0");
+      string runName = "Snapshot " + time + "s " + algorithm.Name;
       Run run;
       if (StoreAlgorithmInEachSnapshot) {
-        run = new Run(runName, algorithm);
+        var temporarilySetStoreFlag = !Algorithm.StoreAlgorithmInEachRun;
+        if (temporarilySetStoreFlag) Algorithm.StoreAlgorithmInEachRun = true;
+        run = new Run(runName, Algorithm);
+        if (temporarilySetStoreFlag) Algorithm.StoreAlgorithmInEachRun = false;
       } else {
         // duplicate code of Run.Initialize - necessary, because Algorithm property doesn't have a setter
@@ -339,4 +398,8 @@
     }
 
+    public void Snapshot() {
+      Task.Factory.StartNew(DoSnapshot);
+    }
+
     public void Prepare() {
       Prepare(false);
@@ -434,4 +497,5 @@
     }
     private void Algorithm_Paused(object sender, EventArgs e) {
+      algorithmStarted.Reset();
       algorithmPaused.Set();
       algorithmStopped.Reset();
@@ -439,4 +503,5 @@
     }
     private void Algorithm_Prepared(object sender, EventArgs e) {
+      algorithmStarted.Reset();
       algorithmPaused.Reset();
       algorithmStopped.Reset();
@@ -448,26 +513,37 @@
     }
     private void Algorithm_Started(object sender, EventArgs e) {
+      algorithmStarted.Set();
       algorithmPaused.Reset();
       algorithmStopped.Reset();
       var execTime = ExecutionTime;
-      var interval = GetNextInterval(execTime);
-      if (interval.HasValue) {
-        snapTimer.Interval = interval.Value;
-        snapTimer.Start();
+      if (snapshotTimesDirty) {
+        SnapshotTimes.Sort();
+        snapshotTimesDirty = false; // sort will mark it dirty again
+        FindNextSnapshotTimeIndex(execTime);
       }
       runTimer.Interval = (MaximumExecutionTime - execTime).TotalMilliseconds;
+      snapTimer.Start();
       runTimer.Start();
       OnStarted();
     }
     private void Algorithm_Stopped(object sender, EventArgs e) {
+      algorithmStarted.Reset();
       algorithmPaused.Reset();
       algorithmStopped.Set();
-      snapTimer.Stop();
-      runTimer.Stop();
-      MakeSnapshot();
-      var snapshotsRun = new Run() { Name = algorithm.Runs.Last().Name };
-      foreach (var s in snapshots)
-        snapshotsRun.Parameters.Add(s.Name, s);
-      Runs.Add(snapshotsRun);
+      lock (snapshotLock) {
+        snapTimer.Stop();
+        runTimer.Stop();
+        MakeSnapshot();
+      }
+      var cloner = new Cloner();
+      var algRun = cloner.Clone(Algorithm.Runs.Last());
+      var clonedSnapshots = cloner.Clone(snapshots);
+      try {
+        algRun.Results.Add("Snapshots", clonedSnapshots);
+      } catch (ArgumentException ex) {
+        // TODO strategy?
+      }
+      Runs.Add(algRun);
+      Algorithm.Runs.Clear();
       OnStopped();
     }
