Index: /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/Views/RefreshableHiveExperimentView.Designer.cs
===================================================================
--- /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/Views/RefreshableHiveExperimentView.Designer.cs	(revision 6443)
+++ /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/Views/RefreshableHiveExperimentView.Designer.cs	(revision 6444)
@@ -254,5 +254,5 @@
       this.resourceNamesTextBox.Location = new System.Drawing.Point(73, 53);
       this.resourceNamesTextBox.Name = "resourceNamesTextBox";
-      this.resourceNamesTextBox.Size = new System.Drawing.Size(304, 20);
+      this.resourceNamesTextBox.Size = new System.Drawing.Size(415, 20);
       this.resourceNamesTextBox.TabIndex = 14;
       this.resourceNamesTextBox.Validated += new System.EventHandler(this.resourceNamesTextBox_Validated);
@@ -292,5 +292,5 @@
       this.isPrivilegedCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
       this.isPrivilegedCheckBox.AutoSize = true;
-      this.isPrivilegedCheckBox.Location = new System.Drawing.Point(383, 55);
+      this.isPrivilegedCheckBox.Location = new System.Drawing.Point(494, 55);
       this.isPrivilegedCheckBox.Name = "isPrivilegedCheckBox";
       this.isPrivilegedCheckBox.Size = new System.Drawing.Size(80, 17);
@@ -299,5 +299,5 @@
       this.toolTip.SetToolTip(this.isPrivilegedCheckBox, "If checked, the job will be executed in a privileged sandbox on the slave.");
       this.isPrivilegedCheckBox.UseVisualStyleBackColor = true;
-      this.isPrivilegedCheckBox.CheckedChanged += new System.EventHandler(this.isPrivilegedCheckBox_CheckedChanged);
+      this.isPrivilegedCheckBox.Validated += new System.EventHandler(this.isPrivilegedCheckBox_Validated);
       // 
       // refreshAutomaticallyCheckBox
@@ -310,5 +310,5 @@
       this.refreshAutomaticallyCheckBox.Text = "&Refresh Automatically";
       this.refreshAutomaticallyCheckBox.UseVisualStyleBackColor = true;
-      this.refreshAutomaticallyCheckBox.CheckedChanged += new System.EventHandler(this.refreshAutomaticallyCheckBox_CheckedChanged);
+      this.refreshAutomaticallyCheckBox.Validated += new System.EventHandler(this.refreshAutomaticallyCheckBox_Validated);
       // 
       // infoGroupBox
Index: /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/Views/RefreshableHiveExperimentView.cs
===================================================================
--- /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/Views/RefreshableHiveExperimentView.cs	(revision 6443)
+++ /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.4/Views/RefreshableHiveExperimentView.cs	(revision 6444)
@@ -281,5 +281,5 @@
     #region Control events
     private void startButton_Click(object sender, EventArgs e) {
-      HiveClient.StartExperiment((Exception ex) => ErrorHandling.ShowErrorDialog(this, "Start failed.", ex), Content);
+      HiveClient.StartExperiment((Exception ex) => ErrorHandling.ShowErrorDialog(this, "Start failed.", ex), Content, new CancellationToken());
     }
     private void pauseButton_Click(object sender, EventArgs e) {
@@ -301,15 +301,9 @@
     }
 
-    private void includeJobsCheckBox_CheckedChanged(object sender, EventArgs e) {
-      //if (Content != null) Content.IncludeJobs = includeJobsCheckBox.Checked;
-    }
-
-    private void refreshAutomaticallyCheckBox_CheckedChanged(object sender, EventArgs e) {
-      if (Content != null) {
-        Content.RefreshAutomatically = refreshAutomaticallyCheckBox.Checked;
-      }
-    }
-
-    private void isPrivilegedCheckBox_CheckedChanged(object sender, EventArgs e) {
+    private void refreshAutomaticallyCheckBox_Validated(object sender, EventArgs e) {
+      if (Content != null) Content.RefreshAutomatically = refreshAutomaticallyCheckBox.Checked;
+    }
+
+    private void isPrivilegedCheckBox_Validated(object sender, EventArgs e) {
       if (Content != null) Content.HiveExperiment.IsPrivileged = isPrivilegedCheckBox.Checked;
     }
Index: /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/HiveClient.cs
===================================================================
--- /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/HiveClient.cs	(revision 6443)
+++ /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/HiveClient.cs	(revision 6444)
@@ -27,4 +27,5 @@
 using System.Security.Cryptography;
 using System.Threading;
+using System.Threading.Tasks;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
@@ -104,8 +105,8 @@
 
     #region Store
-    public static void Store(IHiveItem item) {
+    public static void Store(IHiveItem item, CancellationToken cancellationToken) {
       if (item.Id == Guid.Empty) {
         if (item is RefreshableHiveExperiment) {
-          HiveClient.Instance.UploadExperiment((RefreshableHiveExperiment)item);
+          HiveClient.Instance.UploadExperiment((RefreshableHiveExperiment)item, cancellationToken);
         }
       } else {
@@ -114,8 +115,8 @@
       }
     }
-    public static void StoreAsync(Action<Exception> exceptionCallback, IHiveItem item) {
+    public static void StoreAsync(Action<Exception> exceptionCallback, IHiveItem item, CancellationToken cancellationToken) {
       var call = new Func<Exception>(delegate() {
         try {
-          Store(item);
+          Store(item, cancellationToken);
         }
         catch (Exception ex) {
@@ -159,10 +160,10 @@
     #endregion
 
-    public static void StartExperiment(Action<Exception> exceptionCallback, RefreshableHiveExperiment refreshableHiveExperiment) {
+    public static void StartExperiment(Action<Exception> exceptionCallback, RefreshableHiveExperiment refreshableHiveExperiment, CancellationToken cancellationToken) {
       HiveClient.StoreAsync(
         new Action<Exception>((Exception ex) => {
           refreshableHiveExperiment.HiveExperiment.ExecutionState = ExecutionState.Prepared;
           exceptionCallback(ex);
-        }), refreshableHiveExperiment);
+        }), refreshableHiveExperiment, cancellationToken);
       refreshableHiveExperiment.HiveExperiment.ExecutionState = ExecutionState.Started;
     }
@@ -189,46 +190,55 @@
 
     #region Upload Experiment
-    private void UploadExperiment(RefreshableHiveExperiment refreshableHiveExperiment) {
+    private Semaphore jobUploadSemaphore = new Semaphore(4, 4); // todo: take magic number into config
+    private static object jobCountLocker = new object();
+    private void UploadExperiment(RefreshableHiveExperiment refreshableHiveExperiment, CancellationToken cancellationToken) {
       try {
         refreshableHiveExperiment.HiveExperiment.Progress = new Progress("Connecting to server...");
         refreshableHiveExperiment.HiveExperiment.IsProgressing = true;
-        ServiceLocator.Instance.CallHiveService(service => {
-          IEnumerable<string> resourceNames = ToResourceNameList(refreshableHiveExperiment.HiveExperiment.ResourceNames);
-          var resourceIds = new List<Guid>();
-          foreach (var resourceName in resourceNames) {
-            Guid resourceId = service.GetResourceId(resourceName);
-            if (resourceId == Guid.Empty) {
-              throw new ResourceNotFoundException(string.Format("Could not find the resource '{0}'", resourceName));
-            }
-            resourceIds.Add(resourceId);
+
+        IEnumerable<string> resourceNames = ToResourceNameList(refreshableHiveExperiment.HiveExperiment.ResourceNames);
+        var resourceIds = new List<Guid>();
+        foreach (var resourceName in resourceNames) {
+          Guid resourceId = ServiceLocator.Instance.CallHiveService((s) => s.GetResourceId(resourceName));
+          if (resourceId == Guid.Empty) {
+            throw new ResourceNotFoundException(string.Format("Could not find the resource '{0}'", resourceName));
           }
-
-          foreach (OptimizerHiveJob hiveJob in refreshableHiveExperiment.HiveExperiment.HiveJobs.OfType<OptimizerHiveJob>()) {
-            hiveJob.SetIndexInParentOptimizerList(null);
-          }
-
-          // upload HiveExperiment
-          refreshableHiveExperiment.HiveExperiment.Progress.Status = "Uploading HiveExperiment...";
-          refreshableHiveExperiment.HiveExperiment.Id = service.AddHiveExperiment(refreshableHiveExperiment.HiveExperiment);
-
-          int totalJobCount = refreshableHiveExperiment.HiveExperiment.GetAllHiveJobs().Count();
-          int jobCount = 0;
-
-          // upload plugins
-          refreshableHiveExperiment.HiveExperiment.Progress.Status = "Uploading plugins...";
-          this.OnlinePlugins = service.GetPlugins();
-          this.AlreadyUploadedPlugins = new List<Plugin>();
-          Plugin configFilePlugin = UploadConfigurationFile(service, onlinePlugins);
-          this.alreadyUploadedPlugins.Add(configFilePlugin);
-
-          // upload jobs
-          refreshableHiveExperiment.HiveExperiment.Progress.Status = "Uploading jobs...";
-
-          foreach (HiveJob hiveJob in refreshableHiveExperiment.HiveExperiment.HiveJobs) {
-            UploadJobWithChildren(refreshableHiveExperiment.HiveExperiment.Progress, service, hiveJob, null, resourceIds, ref jobCount, totalJobCount, configFilePlugin.Id, refreshableHiveExperiment.HiveExperiment.Id, refreshableHiveExperiment.Log, refreshableHiveExperiment.HiveExperiment.IsPrivileged);
-          }
-
-          if (refreshableHiveExperiment.RefreshAutomatically) refreshableHiveExperiment.StartResultPolling();
-        });
+          resourceIds.Add(resourceId);
+        }
+
+        foreach (OptimizerHiveJob hiveJob in refreshableHiveExperiment.HiveExperiment.HiveJobs.OfType<OptimizerHiveJob>()) {
+          hiveJob.SetIndexInParentOptimizerList(null);
+        }
+
+        // upload HiveExperiment
+        refreshableHiveExperiment.HiveExperiment.Progress.Status = "Uploading HiveExperiment...";
+        refreshableHiveExperiment.HiveExperiment.Id = ServiceLocator.Instance.CallHiveService((s) => s.AddHiveExperiment(refreshableHiveExperiment.HiveExperiment));
+        cancellationToken.ThrowIfCancellationRequested();
+
+        int totalJobCount = refreshableHiveExperiment.HiveExperiment.GetAllHiveJobs().Count();
+        int[] jobCount = new int[1]; // use a reference type (int-array) instead of value type (int) in order to pass the value via a delegate to task-parallel-library
+        cancellationToken.ThrowIfCancellationRequested();
+
+        // upload plugins
+        refreshableHiveExperiment.HiveExperiment.Progress.Status = "Uploading plugins...";
+        this.OnlinePlugins = ServiceLocator.Instance.CallHiveService((s) => s.GetPlugins());
+        this.AlreadyUploadedPlugins = new List<Plugin>();
+        Plugin configFilePlugin = ServiceLocator.Instance.CallHiveService((s) => UploadConfigurationFile(s, onlinePlugins));
+        this.alreadyUploadedPlugins.Add(configFilePlugin);
+        cancellationToken.ThrowIfCancellationRequested();
+
+        if (refreshableHiveExperiment.RefreshAutomatically) refreshableHiveExperiment.StartResultPolling();
+
+        // upload jobs
+        refreshableHiveExperiment.HiveExperiment.Progress.Status = "Uploading jobs...";
+
+        var tasks = new List<Task>();
+        foreach (HiveJob hiveJob in refreshableHiveExperiment.HiveExperiment.HiveJobs) {
+          tasks.Add(Task.Factory.StartNew((hj) => {
+            UploadJobWithChildren(refreshableHiveExperiment.HiveExperiment.Progress, (HiveJob)hj, null, resourceIds, jobCount, totalJobCount, configFilePlugin.Id, refreshableHiveExperiment.HiveExperiment.Id, refreshableHiveExperiment.Log, refreshableHiveExperiment.HiveExperiment.IsPrivileged, cancellationToken);
+          }, hiveJob)
+          .ContinueWith((x) => refreshableHiveExperiment.Log.LogException(x.Exception), TaskContinuationOptions.OnlyOnFaulted));
+        }
+        Task.WaitAll(tasks.ToArray());
       }
       finally {
@@ -267,45 +277,67 @@
     /// Uploads the given job and all its child-jobs while setting the proper parentJobId values for the childs
     /// </summary>
-    /// <param name="service"></param>
-    /// <param name="hiveJob"></param>
     /// <param name="parentHiveJob">shall be null if its the root job</param>
-    /// <param name="groups"></param>
-    private void UploadJobWithChildren(IProgress progress, IHiveService service, HiveJob hiveJob, HiveJob parentHiveJob, IEnumerable<Guid> groups, ref int jobCount, int totalJobCount, Guid configPluginId, Guid hiveExperimentId, ILog log, bool isPrivileged) {
-      jobCount++;
-      progress.Status = string.Format("Serializing job {0} of {1}", jobCount, totalJobCount);
-      JobData jobData;
-      List<IPluginDescription> plugins;
-
-      if (hiveJob.ItemJob.ComputeInParallel && (hiveJob.ItemJob.Item is Optimization.Experiment || hiveJob.ItemJob.Item is Optimization.BatchRun)) {
-        hiveJob.Job.IsParentJob = true;
-        hiveJob.Job.FinishWhenChildJobsFinished = true;
-        jobData = hiveJob.GetAsJobData(true, out plugins);
-      } else {
-        hiveJob.Job.IsParentJob = false;
-        hiveJob.Job.FinishWhenChildJobsFinished = false;
-        jobData = hiveJob.GetAsJobData(false, out plugins);
-      }
-
-      TryAndRepeat(() => {
-        hiveJob.Job.PluginsNeededIds = PluginUtil.GetPluginDependencies(service, this.onlinePlugins, this.alreadyUploadedPlugins, plugins);
-      }, -1, "Failed to upload plugins");
-      hiveJob.Job.PluginsNeededIds.Add(configPluginId);
-      hiveJob.Job.HiveExperimentId = hiveExperimentId;
-      hiveJob.Job.IsPrivileged = isPrivileged;
-
-      progress.Status = string.Format("Uploading job {0} of {1} ({2} kb, {3} objects)", jobCount, totalJobCount, jobData.Data.Count() / 1024, hiveJob.ItemJob.GetObjectGraphObjects().Count());
-      progress.ProgressValue = (double)jobCount / totalJobCount;
-
-      log.LogMessage(progress.Status);
-      TryAndRepeat(() => {
-        if (parentHiveJob != null) {
-          hiveJob.Job.Id = service.AddChildJob(parentHiveJob.Job.Id, hiveJob.Job, jobData);
-        } else {
-          hiveJob.Job.Id = service.AddJob(hiveJob.Job, jobData, groups.ToList());
-        }
-      }, -1, "Failed to add job", log);
-
-      foreach (HiveJob child in hiveJob.ChildHiveJobs) {
-        UploadJobWithChildren(progress, service, child, hiveJob, groups, ref jobCount, totalJobCount, configPluginId, hiveExperimentId, log, isPrivileged);
+    private void UploadJobWithChildren(IProgress progress, HiveJob hiveJob, HiveJob parentHiveJob, IEnumerable<Guid> groups, int[] jobCount, int totalJobCount, Guid configPluginId, Guid hiveExperimentId, ILog log, bool isPrivileged, CancellationToken cancellationToken) {
+      jobUploadSemaphore.WaitOne();
+      try {
+        cancellationToken.ThrowIfCancellationRequested();
+        lock (jobCountLocker) {
+          jobCount[0]++;
+        }
+        JobData jobData = null;
+        List<IPluginDescription> plugins = null;
+
+        TryAndRepeat(() => { // workaround for persistence bug (thread-safe access to bitmaps) - remove later
+          if (hiveJob.ItemJob.ComputeInParallel && (hiveJob.ItemJob.Item is Optimization.Experiment || hiveJob.ItemJob.Item is Optimization.BatchRun)) {
+            hiveJob.Job.IsParentJob = true;
+            hiveJob.Job.FinishWhenChildJobsFinished = true;
+            jobData = hiveJob.GetAsJobData(true, out plugins);
+          } else {
+            hiveJob.Job.IsParentJob = false;
+            hiveJob.Job.FinishWhenChildJobsFinished = false;
+            jobData = hiveJob.GetAsJobData(false, out plugins);
+          }
+        }, 30, "Could not serialize job");
+        cancellationToken.ThrowIfCancellationRequested();
+
+        TryAndRepeat(() => {
+          if (!cancellationToken.IsCancellationRequested) {
+            ServiceLocator.Instance.CallHiveService((s) => hiveJob.Job.PluginsNeededIds = PluginUtil.GetPluginDependencies(s, this.onlinePlugins, this.alreadyUploadedPlugins, plugins));
+          }
+        }, -1, "Failed to upload plugins");
+        cancellationToken.ThrowIfCancellationRequested();
+        hiveJob.Job.PluginsNeededIds.Add(configPluginId);
+        hiveJob.Job.HiveExperimentId = hiveExperimentId;
+        hiveJob.Job.IsPrivileged = isPrivileged;
+
+        log.LogMessage(string.Format("Uploading job ({0} kb, {1} objects)", jobData.Data.Count() / 1024, hiveJob.ItemJob.GetObjectGraphObjects().Count()));
+        TryAndRepeat(() => {
+          if (!cancellationToken.IsCancellationRequested) {
+            if (parentHiveJob != null) {
+              hiveJob.Job.Id = ServiceLocator.Instance.CallHiveService((s) => s.AddChildJob(parentHiveJob.Job.Id, hiveJob.Job, jobData));
+            } else {
+              hiveJob.Job.Id = ServiceLocator.Instance.CallHiveService((s) => s.AddJob(hiveJob.Job, jobData, groups.ToList()));
+            }
+          }
+        }, 50, "Failed to add job", log);
+        cancellationToken.ThrowIfCancellationRequested();
+
+        lock (jobCountLocker) {
+          progress.ProgressValue = (double)jobCount[0] / totalJobCount;
+          progress.Status = string.Format("Uploaded job ({0} of {1})", jobCount[0], totalJobCount);
+        }
+
+        var tasks = new List<Task>();
+        foreach (HiveJob child in hiveJob.ChildHiveJobs) {
+          tasks.Add(Task.Factory.StartNew((tuple) => {
+            var arguments = (Tuple<HiveJob, HiveJob>)tuple;
+            UploadJobWithChildren(progress, arguments.Item1, arguments.Item2, groups, jobCount, totalJobCount, configPluginId, hiveExperimentId, log, isPrivileged, cancellationToken);
+          }, new Tuple<HiveJob, HiveJob>(child, hiveJob ))
+          .ContinueWith((x) => log.LogException(x.Exception), TaskContinuationOptions.OnlyOnFaulted));
+        }
+        Task.WaitAll(tasks.ToArray());
+      }
+      finally {
+        jobUploadSemaphore.Release();
       }
     }
Index: /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/ServiceClients/HiveItem.cs
===================================================================
--- /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/ServiceClients/HiveItem.cs	(revision 6443)
+++ /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/ServiceClients/HiveItem.cs	(revision 6444)
@@ -86,5 +86,5 @@
 
     public void Store() {
-      HiveClient.Store(this);
+      HiveClient.Store(this, new System.Threading.CancellationToken());
       Modified = false;
     }
Index: /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/Util/PluginUtil.cs
===================================================================
--- /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/Util/PluginUtil.cs	(revision 6443)
+++ /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/Util/PluginUtil.cs	(revision 6444)
@@ -30,4 +30,5 @@
 namespace HeuristicLab.Clients.Hive {
   public static class PluginUtil {
+    private static object locker = new object();
 
     /// <summary>
@@ -40,37 +41,39 @@
     /// <returns></returns>
     public static List<Guid> GetPluginDependencies(IHiveService service, List<Plugin> onlinePlugins, List<Plugin> alreadyUploadedPlugins, IEnumerable<IPluginDescription> neededPlugins) {
-      var pluginIds = new List<Guid>();
-      Dictionary<IPluginDescription, byte[]> checksumsNeededPlugins = CalcChecksumsForPlugins(neededPlugins);
+      lock (locker) {
+        var pluginIds = new List<Guid>();
+        Dictionary<IPluginDescription, byte[]> checksumsNeededPlugins = CalcChecksumsForPlugins(neededPlugins);
 
-      foreach (var neededPlugin in checksumsNeededPlugins) {
-        Plugin foundPlugin = alreadyUploadedPlugins.FirstOrDefault(p => p.Hash.SequenceEqual(neededPlugin.Value));
-        if (foundPlugin == null) {
-          foundPlugin = onlinePlugins.FirstOrDefault(p => {
-            if (p.Hash != null) {
-              return p.Hash.SequenceEqual(neededPlugin.Value);
+        foreach (var neededPlugin in checksumsNeededPlugins) {
+          Plugin foundPlugin = alreadyUploadedPlugins.FirstOrDefault(p => p.Hash.SequenceEqual(neededPlugin.Value));
+          if (foundPlugin == null) {
+            foundPlugin = onlinePlugins.FirstOrDefault(p => {
+              if (p.Hash != null) {
+                return p.Hash.SequenceEqual(neededPlugin.Value);
+              } else {
+                return false;
+              }
+            });
+
+            if (foundPlugin == null) {
+              Plugin p = CreatePlugin(neededPlugin.Key, neededPlugin.Value);
+              List<PluginData> pd = CreatePluginDatas(neededPlugin.Key);
+              try {
+                p.Id = service.AddPlugin(p, pd);
+                alreadyUploadedPlugins.Add(p);
+                pluginIds.Add(p.Id);
+              }
+              catch (FaultException<PluginAlreadyExistsFault> fault) {
+                onlinePlugins.Add(service.GetPlugin(fault.Detail.Id));
+              }
             } else {
-              return false;
-            }
-          });
-
-          if (foundPlugin == null) {
-            Plugin p = CreatePlugin(neededPlugin.Key, neededPlugin.Value);
-            List<PluginData> pd = CreatePluginDatas(neededPlugin.Key);
-            try {
-              p.Id = service.AddPlugin(p, pd);
-              alreadyUploadedPlugins.Add(p);
-              pluginIds.Add(p.Id);
-            }
-            catch (FaultException<PluginAlreadyExistsFault> fault) {
-              onlinePlugins.Add(service.GetPlugin(fault.Detail.Id));
+              pluginIds.Add(foundPlugin.Id);
             }
           } else {
             pluginIds.Add(foundPlugin.Id);
           }
-        } else {
-          pluginIds.Add(foundPlugin.Id);
         }
+        return pluginIds;
       }
-      return pluginIds;
     }
 
Index: /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.HiveEngine.Views/3.4/HiveEngineView.Designer.cs
===================================================================
--- /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.HiveEngine.Views/3.4/HiveEngineView.Designer.cs	(revision 6443)
+++ /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.HiveEngine.Views/3.4/HiveEngineView.Designer.cs	(revision 6444)
@@ -60,5 +60,5 @@
       this.resourceIdsTextBox.Location = new System.Drawing.Point(189, 52);
       this.resourceIdsTextBox.Name = "resourceIdsTextBox";
-      this.resourceIdsTextBox.Size = new System.Drawing.Size(319, 20);
+      this.resourceIdsTextBox.Size = new System.Drawing.Size(428, 20);
       this.resourceIdsTextBox.TabIndex = 4;
       this.resourceIdsTextBox.Text = "HEAL";
@@ -184,5 +184,5 @@
       this.isPrivilegedCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
       this.isPrivilegedCheckBox.AutoSize = true;
-      this.isPrivilegedCheckBox.Location = new System.Drawing.Point(514, 55);
+      this.isPrivilegedCheckBox.Location = new System.Drawing.Point(623, 54);
       this.isPrivilegedCheckBox.Name = "isPrivilegedCheckBox";
       this.isPrivilegedCheckBox.Size = new System.Drawing.Size(80, 17);
@@ -190,5 +190,5 @@
       this.isPrivilegedCheckBox.Text = "IsPrivileged";
       this.isPrivilegedCheckBox.UseVisualStyleBackColor = true;
-      this.isPrivilegedCheckBox.CheckedChanged += new System.EventHandler(this.isPrivilegedCheckBox_CheckedChanged);
+      this.isPrivilegedCheckBox.Validated += new System.EventHandler(this.isPrivilegedCheckBox_Validated);
       // 
       // HiveEngineView
Index: /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.HiveEngine.Views/3.4/HiveEngineView.cs
===================================================================
--- /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.HiveEngine.Views/3.4/HiveEngineView.cs	(revision 6443)
+++ /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.HiveEngine.Views/3.4/HiveEngineView.cs	(revision 6444)
@@ -109,10 +109,8 @@
     }
 
-    private void isPrivilegedCheckBox_CheckedChanged(object sender, EventArgs e) {
+    private void isPrivilegedCheckBox_Validated(object sender, EventArgs e) {
       Content.IsPrivileged = isPrivilegedCheckBox.Checked;
     }
     #endregion
-
-
   }
 }
Index: /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.HiveEngine/3.4/HiveEngine.cs
===================================================================
--- /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.HiveEngine/3.4/HiveEngine.cs	(revision 6443)
+++ /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.HiveEngine/3.4/HiveEngine.cs	(revision 6444)
@@ -256,5 +256,5 @@
             random.Reset(random.Next());
         }
-        HiveClient.StartExperiment((e) => { log.LogException(e); }, refreshableHiveExperiment);
+        HiveClient.StartExperiment((e) => { log.LogException(e); }, refreshableHiveExperiment, cancellationToken);
 
         // do polling until experiment is finished and all jobs are downloaded
Index: /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.DataAccess/3.4/TransactionManager.cs
===================================================================
--- /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.DataAccess/3.4/TransactionManager.cs	(revision 6443)
+++ /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.DataAccess/3.4/TransactionManager.cs	(revision 6444)
@@ -27,26 +27,45 @@
   public static class TransactionManager {
     public static void UseTransaction(Action call, bool serializable = false, bool longRunning = false) {
-      TransactionScope transaction = CreateTransaction(serializable, longRunning);
-      try {
-        call();
-        transaction.Complete();
-      }
-      finally {
-        transaction.Dispose();
+      int n = 10;
+      while (n > 0) {
+        TransactionScope transaction = CreateTransaction(serializable, longRunning);
+        try {
+          call();
+          transaction.Complete();
+          n = 0;
+        }
+        catch (System.Data.SqlClient.SqlException e) {
+          n--; // probably deadlock situation, let it roll back and repeat the transaction n times
+          LogFactory.GetLogger(typeof(TransactionManager).Namespace).Log(string.Format("Exception occured, repeating transaction {0} more times. Details: {1}", n, e.ToString()));          
+          if (n <= 0) throw;
+        }
+        finally {
+          transaction.Dispose();
+        }
       }
     }
 
     public static T UseTransaction<T>(Func<T> call, bool serializable = false, bool longRunning = false) {
-      TransactionScope transaction = CreateTransaction(serializable, longRunning);
-      try {
-        T result = call();
-        transaction.Complete();
-        return result;
+      int n = 10;
+      while (n > 0) {
+        TransactionScope transaction = CreateTransaction(serializable, longRunning);
+        try {
+          T result = call();
+          transaction.Complete();
+          n = 0;
+          return result;
+        }
+        catch (System.Data.SqlClient.SqlException e) {
+          n--; // probably deadlock situation, let it roll back and repeat the transaction n times
+          LogFactory.GetLogger(typeof(TransactionManager).Namespace).Log(string.Format("Exception occured, repeating transaction {0} more times. Details: {1}", n, e.ToString()));
+          if (n <= 0) throw;
+        }
+        finally {
+          transaction.Dispose();
+        }
       }
-      finally {
-        transaction.Dispose();
-      }
+      throw new Exception("This code should not be reached");
     }
-    
+
     private static TransactionScope CreateTransaction(bool serializable, bool longRunning) {
       var options = new TransactionOptions();
@@ -58,5 +77,5 @@
       if (longRunning)
         options.Timeout = ApplicationConstants.LongRunningDatabaseCommandTimeout;
-      
+
       return new TransactionScope(TransactionScopeOption.Required, options);
     }
Index: /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/HeartbeatManager.cs
===================================================================
--- /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/HeartbeatManager.cs	(revision 6443)
+++ /branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.4/HeartbeatManager.cs	(revision 6444)
@@ -62,6 +62,6 @@
           if (availableJobs.Count() > 0) {
             var job = availableJobs.First();
-            actions.Add(new MessageContainer(MessageContainer.MessageType.CalculateJob, job.Id));
-            AssignJob(slave, job);
+            if (AssignJob(slave, job))
+              actions.Add(new MessageContainer(MessageContainer.MessageType.CalculateJob, job.Id));
           }
         }
@@ -70,11 +70,15 @@
     }
 
-    private void AssignJob(Slave slave, Job job) {
+    // returns true if assignment was successful
+    private bool AssignJob(Slave slave, Job job) {
+      // load job again and check if it is still available (this is an attempt to reduce the race condition which causes multiple heartbeats to get the same job assigned)
+      if (dao.GetJob(job.Id).State != JobState.Waiting) return false;
+
       job = dao.UpdateJobState(job.Id, JobState.Transferring, slave.Id, null, null);
-      dao.UpdateSlave(slave);
 
       // from now on the job has some time to send the next heartbeat (ApplicationConstants.TransferringJobHeartbeatTimeout)
       job.LastHeartbeat = DateTime.Now;
       dao.UpdateJob(job);
+      return true;
     }
 
