Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.3/Views/HiveExperimentManagerView.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.3/Views/HiveExperimentManagerView.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.3/Views/HiveExperimentManagerView.cs	(revision 6725)
@@ -68,5 +68,5 @@
         hiveExperimentListView.Content = null;
       } else {
-        hiveExperimentListView.Content = Content.HiveExperiments;
+        hiveExperimentListView.Content = Content.Jobs;
         if (Content != null)
           Content.RefreshAsync(new Action<Exception>((Exception ex) => ErrorHandling.ShowErrorDialog(this, "Refresh failed.", ex)));
@@ -93,5 +93,5 @@
         Invoke(new EventHandler(Content_Refreshed), sender, e);
       } else {
-        hiveExperimentListView.Content = Content.HiveExperiments;
+        hiveExperimentListView.Content = Content.Jobs;
         refreshButton.Enabled = true;
         hiveExperimentListView.Enabled = true;
@@ -106,6 +106,6 @@
     protected override void OnClosing(FormClosingEventArgs e) {
       base.OnClosing(e);
-      if (Content != null && Content.HiveExperiments != null) {
-        foreach (var exp in Content.HiveExperiments.OfType<RefreshableHiveExperiment>()) {
+      if (Content != null && Content.Jobs != null) {
+        foreach (var exp in Content.Jobs.OfType<RefreshableJob>()) {
           if (exp.RefreshAutomatically) {
             exp.RefreshAutomatically = false; // stop result polling
@@ -115,5 +115,5 @@
     }
 
-    private void HiveExperiments_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<RefreshableHiveExperiment> e) {
+    private void HiveExperiments_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<RefreshableJob> e) {
       foreach (var item in e.Items) {
         HiveClient.Delete(item);
@@ -122,5 +122,5 @@
 
     private void Content_HiveExperimentsChanged(object sender, EventArgs e) {
-      Content.HiveExperiments.ItemsRemoved += new CollectionItemsChangedEventHandler<RefreshableHiveExperiment>(HiveExperiments_ItemsRemoved);
+      Content.Jobs.ItemsRemoved += new CollectionItemsChangedEventHandler<RefreshableJob>(HiveExperiments_ItemsRemoved);
     }
   }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.3/Views/RefreshableHiveExperimentListView.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.3/Views/RefreshableHiveExperimentListView.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.3/Views/RefreshableHiveExperimentListView.cs	(revision 6725)
@@ -28,6 +28,6 @@
 namespace HeuristicLab.Clients.Hive.ExperimentManager.Views {
   [View("HiveExperimentList View")]
-  [Content(typeof(ItemCollection<RefreshableHiveExperiment>), false)]
-  public partial class RefreshableHiveExperimentListView : ItemCollectionView<RefreshableHiveExperiment> {
+  [Content(typeof(ItemCollection<RefreshableJob>), false)]
+  public partial class RefreshableHiveExperimentListView : ItemCollectionView<RefreshableJob> {
 
     public RefreshableHiveExperimentListView() {
@@ -43,6 +43,6 @@
     }
 
-    protected override RefreshableHiveExperiment CreateItem() {
-      return new RefreshableHiveExperiment() { IsAllowedPrivileged = HiveClient.Instance.IsAllowedPrivileged };
+    protected override RefreshableJob CreateItem() {
+      return new RefreshableJob() { IsAllowedPrivileged = HiveClient.Instance.IsAllowedPrivileged };
     }
 
@@ -54,15 +54,15 @@
     }
 
-    protected override void Content_ItemsAdded(object sender, Collections.CollectionItemsChangedEventArgs<RefreshableHiveExperiment> e) {
+    protected override void Content_ItemsAdded(object sender, Collections.CollectionItemsChangedEventArgs<RefreshableJob> e) {
       base.Content_ItemsAdded(sender, e);
 
     }
 
-    protected override ListViewItem CreateListViewItem(RefreshableHiveExperiment item) {
+    protected override ListViewItem CreateListViewItem(RefreshableJob item) {
       ListViewItem listViewItem = base.CreateListViewItem(item);
       listViewItem.SubItems.Clear();
-      listViewItem.SubItems.Insert(0, new ListViewItem.ListViewSubItem(listViewItem, item.HiveExperiment.DateCreated.ToString("dd.MM.yyyy HH:mm")));
-      listViewItem.SubItems.Insert(1, new ListViewItem.ListViewSubItem(listViewItem, item.HiveExperiment.Name));
-      listViewItem.Group = GetListViewGroup(item.HiveExperiment.OwnerUsername);
+      listViewItem.SubItems.Insert(0, new ListViewItem.ListViewSubItem(listViewItem, item.Job.DateCreated.ToString("dd.MM.yyyy HH:mm")));
+      listViewItem.SubItems.Insert(1, new ListViewItem.ListViewSubItem(listViewItem, item.Job.Name));
+      listViewItem.Group = GetListViewGroup(item.Job.OwnerUsername);
       return listViewItem;
     }
@@ -70,8 +70,8 @@
     protected override void UpdateListViewItemText(ListViewItem listViewItem) {
       if (listViewItem == null) throw new ArgumentNullException();
-      var item = listViewItem.Tag as RefreshableHiveExperiment;
-      listViewItem.SubItems[0].Text = item == null ? "null" : item.HiveExperiment.DateCreated.ToString("dd.MM.yyyy HH:mm");
-      listViewItem.SubItems[1].Text = item == null ? "null" : item.HiveExperiment.Name;
-      listViewItem.Group = GetListViewGroup(item.HiveExperiment.OwnerUsername);
+      var item = listViewItem.Tag as RefreshableJob;
+      listViewItem.SubItems[0].Text = item == null ? "null" : item.Job.DateCreated.ToString("dd.MM.yyyy HH:mm");
+      listViewItem.SubItems[1].Text = item == null ? "null" : item.Job.Name;
+      listViewItem.Group = GetListViewGroup(item.Job.OwnerUsername);
       listViewItem.ToolTipText = item == null ? string.Empty : item.ItemName + ": " + item.ItemDescription;
     }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.3/Views/RefreshableHiveExperimentView.Designer.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.3/Views/RefreshableHiveExperimentView.Designer.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.3/Views/RefreshableHiveExperimentView.Designer.cs	(revision 6725)
@@ -339,5 +339,5 @@
       this.isPrivilegedCheckBox.TabIndex = 26;
       this.isPrivilegedCheckBox.Text = "IsPrivileged";
-      this.toolTip.SetToolTip(this.isPrivilegedCheckBox, "If checked, the job will be executed in a privileged sandbox on the slave.");
+      this.toolTip.SetToolTip(this.isPrivilegedCheckBox, "If checked, the task will be executed in a privileged sandbox on the slave.");
       this.isPrivilegedCheckBox.UseVisualStyleBackColor = true;
       this.isPrivilegedCheckBox.Validated += new System.EventHandler(this.isPrivilegedCheckBox_Validated);
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.3/Views/RefreshableHiveExperimentView.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.3/Views/RefreshableHiveExperimentView.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.ExperimentManager/3.3/Views/RefreshableHiveExperimentView.cs	(revision 6725)
@@ -39,10 +39,10 @@
   /// </summary>
   [View("Hive Experiment View")]
-  [Content(typeof(RefreshableHiveExperiment), true)]
+  [Content(typeof(RefreshableJob), true)]
   public sealed partial class RefreshableHiveExperimentView : ItemView {
     private ProgressView progressView;
 
-    public new RefreshableHiveExperiment Content {
-      get { return (RefreshableHiveExperiment)base.Content; }
+    public new RefreshableJob Content {
+      get { return (RefreshableJob)base.Content; }
       set { base.Content = value; }
     }
@@ -58,5 +58,5 @@
       base.RegisterContentEvents();
       Content.RefreshAutomaticallyChanged += new EventHandler(Content_RefreshAutomaticallyChanged);
-      Content.HiveExperimentChanged += new EventHandler(Content_HiveExperimentChanged);
+      Content.JobChanged += new EventHandler(Content_HiveExperimentChanged);
       Content.IsControllableChanged += new EventHandler(Content_IsControllableChanged);
       Content.JobStatisticsChanged += new EventHandler(Content_JobStatisticsChanged);
@@ -72,5 +72,5 @@
     protected override void DeregisterContentEvents() {
       Content.RefreshAutomaticallyChanged -= new EventHandler(Content_RefreshAutomaticallyChanged);
-      Content.HiveExperimentChanged -= new EventHandler(Content_HiveExperimentChanged);
+      Content.JobChanged -= new EventHandler(Content_HiveExperimentChanged);
       Content.IsControllableChanged -= new EventHandler(Content_IsControllableChanged);
       Content.JobStatisticsChanged -= new EventHandler(Content_JobStatisticsChanged);
@@ -85,20 +85,20 @@
 
     private void RegisterHiveExperimentEvents() {
-      Content.HiveExperiment.PropertyChanged += new PropertyChangedEventHandler(HiveExperiment_PropertyChanged);
+      Content.Job.PropertyChanged += new PropertyChangedEventHandler(HiveExperiment_PropertyChanged);
     }
     
     private void DeregisterHiveExperimentEvents() {
-      Content.HiveExperiment.PropertyChanged -= new PropertyChangedEventHandler(HiveExperiment_PropertyChanged);
+      Content.Job.PropertyChanged -= new PropertyChangedEventHandler(HiveExperiment_PropertyChanged);
     }
 
     private void RegisterHiveJobEvents() {
-      Content.HiveJobs.ItemsAdded += new CollectionItemsChangedEventHandler<HiveJob>(HiveJobs_ItemsAdded_Removed_Reset);
-      Content.HiveJobs.ItemsRemoved += new CollectionItemsChangedEventHandler<HiveJob>(HiveJobs_ItemsAdded_Removed_Reset);
-      Content.HiveJobs.CollectionReset += new CollectionItemsChangedEventHandler<HiveJob>(HiveJobs_ItemsAdded_Removed_Reset);
+      Content.HiveJobs.ItemsAdded += new CollectionItemsChangedEventHandler<HiveTask>(HiveJobs_ItemsAdded_Removed_Reset);
+      Content.HiveJobs.ItemsRemoved += new CollectionItemsChangedEventHandler<HiveTask>(HiveJobs_ItemsAdded_Removed_Reset);
+      Content.HiveJobs.CollectionReset += new CollectionItemsChangedEventHandler<HiveTask>(HiveJobs_ItemsAdded_Removed_Reset);
     }
     private void DeregisterHiveJobEvents() {
-      Content.HiveJobs.ItemsAdded -= new CollectionItemsChangedEventHandler<HiveJob>(HiveJobs_ItemsAdded_Removed_Reset);
-      Content.HiveJobs.ItemsRemoved -= new CollectionItemsChangedEventHandler<HiveJob>(HiveJobs_ItemsAdded_Removed_Reset);
-      Content.HiveJobs.CollectionReset -= new CollectionItemsChangedEventHandler<HiveJob>(HiveJobs_ItemsAdded_Removed_Reset);
+      Content.HiveJobs.ItemsAdded -= new CollectionItemsChangedEventHandler<HiveTask>(HiveJobs_ItemsAdded_Removed_Reset);
+      Content.HiveJobs.ItemsRemoved -= new CollectionItemsChangedEventHandler<HiveTask>(HiveJobs_ItemsAdded_Removed_Reset);
+      Content.HiveJobs.CollectionReset -= new CollectionItemsChangedEventHandler<HiveTask>(HiveJobs_ItemsAdded_Removed_Reset);
     }
 
@@ -114,8 +114,8 @@
         logView.Content = null;
       } else {
-        nameTextBox.Text = Content.HiveExperiment.Name;
+        nameTextBox.Text = Content.Job.Name;
         executionTimeTextBox.Text = Content.ExecutionTime.ToString();
-        resourceNamesTextBox.Text = Content.HiveExperiment.ResourceNames;
-        isPrivilegedCheckBox.Checked = Content.HiveExperiment.IsPrivileged;
+        resourceNamesTextBox.Text = Content.Job.ResourceNames;
+        isPrivilegedCheckBox.Checked = Content.Job.IsPrivileged;
         refreshAutomaticallyCheckBox.Checked = Content.RefreshAutomatically;
         logView.Content = Content.Log;
@@ -140,5 +140,5 @@
       if (Content != null) {
         bool alreadyUploaded = Content.Id != Guid.Empty;
-        bool jobsLoaded = Content.HiveJobs != null && Content.HiveJobs.All(x => x.Job.Id != Guid.Empty);
+        bool jobsLoaded = Content.HiveJobs != null && Content.HiveJobs.All(x => x.Task.Id != Guid.Empty);
 
         this.nameTextBox.ReadOnly = !Content.IsControllable || Content.ExecutionState != ExecutionState.Prepared || alreadyUploaded;
@@ -164,7 +164,7 @@
 
     #region Content Events
-    private void HiveJobs_ItemsAdded_Removed_Reset(object sender, CollectionItemsChangedEventArgs<HiveJob> e) {
-      if (InvokeRequired)
-        Invoke(new CollectionItemsChangedEventHandler<HiveJob>(HiveJobs_ItemsAdded_Removed_Reset), sender, e);
+    private void HiveJobs_ItemsAdded_Removed_Reset(object sender, CollectionItemsChangedEventArgs<HiveTask> e) {
+      if (InvokeRequired)
+        Invoke(new CollectionItemsChangedEventHandler<HiveTask>(HiveJobs_ItemsAdded_Removed_Reset), sender, e);
       else {
         SetEnabledStateOfControls();
@@ -240,5 +240,5 @@
 
     private void Content_HiveExperimentChanged(object sender, EventArgs e) {
-      if (Content.HiveExperiment != null) {
+      if (Content.Job != null) {
         RegisterHiveExperimentEvents();
         Content_IsProgressingChanged(sender, e);
@@ -253,7 +253,7 @@
       else {
         if (Content != null) {
-          jobsTextBox.Text = Content.HiveExperiment.JobCount.ToString();
-          calculatingTextBox.Text = Content.HiveExperiment.CalculatingCount.ToString();
-          finishedTextBox.Text = Content.HiveExperiment.FinishedCount.ToString();
+          jobsTextBox.Text = Content.Job.JobCount.ToString();
+          calculatingTextBox.Text = Content.Job.CalculatingCount.ToString();
+          finishedTextBox.Text = Content.Job.FinishedCount.ToString();
         } else {
           jobsTextBox.Text = "0";
@@ -283,5 +283,5 @@
 
     private void UpdateStateLogList() {
-      if (Content != null && this.Content.HiveExperiment != null) {
+      if (Content != null && this.Content.Job != null) {
         stateLogViewHost.Content = this.Content.StateLogList;
       } else {
@@ -291,5 +291,5 @@
 
     private void HiveExperiment_PropertyChanged(object sender, PropertyChangedEventArgs e) {
-      if(this.Content != null && e.PropertyName == "Id") this.hiveExperimentPermissionListView.HiveExperimentId = this.Content.HiveExperiment.Id;
+      if(this.Content != null && e.PropertyName == "Id") this.hiveExperimentPermissionListView.HiveExperimentId = this.Content.Job.Id;
     }
     #endregion
@@ -308,11 +308,11 @@
 
     private void nameTextBox_Validated(object sender, EventArgs e) {
-      if (Content.HiveExperiment.Name != nameTextBox.Text)
-        Content.HiveExperiment.Name = nameTextBox.Text;
+      if (Content.Job.Name != nameTextBox.Text)
+        Content.Job.Name = nameTextBox.Text;
     }
 
     private void resourceNamesTextBox_Validated(object sender, EventArgs e) {
-      if (Content.HiveExperiment.ResourceNames != resourceNamesTextBox.Text)
-        Content.HiveExperiment.ResourceNames = resourceNamesTextBox.Text;
+      if (Content.Job.ResourceNames != resourceNamesTextBox.Text)
+        Content.Job.ResourceNames = resourceNamesTextBox.Text;
     }
 
@@ -322,9 +322,9 @@
 
     private void isPrivilegedCheckBox_Validated(object sender, EventArgs e) {
-      if (Content != null) Content.HiveExperiment.IsPrivileged = isPrivilegedCheckBox.Checked;
+      if (Content != null) Content.Job.IsPrivileged = isPrivilegedCheckBox.Checked;
     }
 
     private void refreshButton_Click(object sender, EventArgs e) {
-      var invoker = new Action<RefreshableHiveExperiment>(HiveClient.LoadExperiment);
+      var invoker = new Action<RefreshableJob>(HiveClient.LoadExperiment);
       invoker.BeginInvoke(Content, (ar) => {
         try {
@@ -338,5 +338,5 @@
 
     private void refreshPermissionsButton_Click(object sender, EventArgs e) {
-      hiveExperimentPermissionListView.Content = HiveClient.GetHiveExperimentPermissions(this.Content.HiveExperiment.Id);
+      hiveExperimentPermissionListView.Content = HiveClient.GetHiveExperimentPermissions(this.Content.Job.Id);
     }
 
@@ -406,5 +406,5 @@
         var optimizer = obj as IOptimizer;
         if (optimizer != null) {
-          Content.HiveJobs.Add(new OptimizerHiveJob(e.Effect.HasFlag(DragDropEffects.Copy) ? (IOptimizer)optimizer.Clone() : optimizer));
+          Content.HiveJobs.Add(new OptimizerHiveTask(e.Effect.HasFlag(DragDropEffects.Copy) ? (IOptimizer)optimizer.Clone() : optimizer));
         }
       }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave.Views/3.3/JobsView.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave.Views/3.3/JobsView.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave.Views/3.3/JobsView.cs	(revision 6725)
@@ -63,7 +63,7 @@
     void Content_SlaveStatusChanged(object sender, Common.EventArgs<StatusCommons> e) {
       lstJobs.Items.Clear();
-      foreach (JobStatus job in e.Value.Jobs) {
+      foreach (TaskStatus job in e.Value.Jobs) {
         ListViewItem item = new ListViewItem();
-        item.Text = job.JobId.ToString();
+        item.Text = job.TaskId.ToString();
         item.SubItems.Add(job.ExecutionTime.ToString());
         lstJobs.Items.Add(item);
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave.Views/3.3/SlaveItem.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave.Views/3.3/SlaveItem.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave.Views/3.3/SlaveItem.cs	(revision 6725)
@@ -202,5 +202,5 @@
       if (diff > 0) {
         if (diff == 1) {
-          OnUserVisibleMessageFired("HeuristicLab Hive received 1 new job!");
+          OnUserVisibleMessageFired("HeuristicLab Hive received 1 new task!");
         } else {
           OnUserVisibleMessageFired(string.Format("HeuristicLab Hive received {0} new jobs!", diff));
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Core.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Core.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Core.cs	(revision 6725)
@@ -50,5 +50,5 @@
     private ServiceHost slaveComm;
     private WcfService wcfService;
-    private JobManager jobManager;
+    private TaskManager taskManager;
     private ConfigManager configManager;
     private PluginManager pluginManager;
@@ -57,10 +57,10 @@
       var log = new ThreadSafeLog(new Log(Settings.Default.MaxLogCount));
       this.pluginManager = new PluginManager(WcfService.Instance, log);
-      this.jobManager = new JobManager(pluginManager, log);
+      this.taskManager = new TaskManager(pluginManager, log);
       log.MessageAdded += new EventHandler<EventArgs<string>>(log_MessageAdded);
 
-      RegisterJobManagerEvents();
-
-      this.configManager = new ConfigManager(jobManager);
+      RegisterTaskManagerEvents();
+
+      this.configManager = new ConfigManager(taskManager);
       ConfigManager.Instance = this.configManager;
     }
@@ -78,5 +78,5 @@
         clientCom = SlaveClientCom.Instance.ClientCom;
 
-        // delete all left over job directories
+        // delete all left over task directories
         pluginManager.CleanPluginTemp();
         clientCom.LogMessage("Hive Slave started");
@@ -149,5 +149,5 @@
     /// <param name="container">The container, containing the message</param>
     private void DetermineAction(MessageContainer container) {
-      clientCom.LogMessage(string.Format("Message: {0} for job: {1} ", container.Message.ToString(), container.TaskId));
+      clientCom.LogMessage(string.Format("Message: {0} for task: {1} ", container.Message.ToString(), container.TaskId));
 
       if (container is ExecutorMessageContainer<Guid>) {
@@ -156,15 +156,15 @@
       } else if (container is MessageContainer) {
         switch (container.Message) {
-          case MessageContainer.MessageType.CalculateJob:
-            CalculateJobAsync(container.TaskId);
-            break;
-          case MessageContainer.MessageType.AbortJob:
-            AbortJobAsync(container.TaskId);
-            break;
-          case MessageContainer.MessageType.StopJob:
-            StopJobAsync(container.TaskId);
-            break;
-          case MessageContainer.MessageType.PauseJob:
-            PauseJobAsync(container.TaskId);
+          case MessageContainer.MessageType.CalculateTask:
+            CalculateTaskAsync(container.TaskId);
+            break;
+          case MessageContainer.MessageType.AbortTask:
+            AbortTaskAsync(container.TaskId);
+            break;
+          case MessageContainer.MessageType.StopTask:
+            StopTaskAsync(container.TaskId);
+            break;
+          case MessageContainer.MessageType.PauseTask:
+            PauseTaskAsync(container.TaskId);
             break;
           case MessageContainer.MessageType.StopAll:
@@ -195,6 +195,6 @@
     }
 
-    private void CalculateJobAsync(Guid jobId) {
-      TS.Task.Factory.StartNew(HandleCalculateJob, jobId)
+    private void CalculateTaskAsync(Guid jobId) {
+      TS.Task.Factory.StartNew(HandleCalculateTask, jobId)
       .ContinueWith((t) => {
         SlaveStatusInfo.IncrementExceptionOccured();
@@ -203,6 +203,6 @@
     }
 
-    private void StopJobAsync(Guid jobId) {
-      TS.Task.Factory.StartNew(HandleStopJob, jobId)
+    private void StopTaskAsync(Guid jobId) {
+      TS.Task.Factory.StartNew(HandleStopTask, jobId)
        .ContinueWith((t) => {
          SlaveStatusInfo.IncrementExceptionOccured();
@@ -211,6 +211,6 @@
     }
 
-    private void PauseJobAsync(Guid jobId) {
-      TS.Task.Factory.StartNew(HandlePauseJob, jobId)
+    private void PauseTaskAsync(Guid jobId) {
+      TS.Task.Factory.StartNew(HandlePauseTask, jobId)
        .ContinueWith((t) => {
          SlaveStatusInfo.IncrementExceptionOccured();
@@ -219,6 +219,6 @@
     }
 
-    private void AbortJobAsync(Guid jobId) {
-      TS.Task.Factory.StartNew(HandleAbortJob, jobId)
+    private void AbortTaskAsync(Guid jobId) {
+      TS.Task.Factory.StartNew(HandleAbortTask, jobId)
        .ContinueWith((t) => {
          SlaveStatusInfo.IncrementExceptionOccured();
@@ -227,58 +227,58 @@
     }
 
-    private void HandleCalculateJob(object jobIdObj) {
-      Guid jobId = (Guid)jobIdObj;
-      Task job = null;
+    private void HandleCalculateTask(object taskIdObj) {
+      Guid taskId = (Guid)taskIdObj;
+      Task task = null;
       int usedCores = 0;
       try {
-        job = wcfService.GetJob(jobId);
-        if (job == null) throw new JobNotFoundException(jobId);
-        if (ConfigManager.Instance.GetFreeCores() < job.CoresNeeded) throw new OutOfCoresException();
-        if (ConfigManager.GetFreeMemory() < job.MemoryNeeded) throw new OutOfMemoryException();
-        SlaveStatusInfo.IncrementUsedCores(job.CoresNeeded); usedCores = job.CoresNeeded;
-        TaskData jobData = wcfService.GetJobData(jobId);
-        if (jobData == null) throw new JobDataNotFoundException(jobId);
-        job = wcfService.UpdateJobState(jobId, TaskState.Calculating, null);
-        if (job == null) throw new JobNotFoundException(jobId);
-        jobManager.StartJobAsync(job, jobData);
-      }
-      catch (JobNotFoundException) {
+        task = wcfService.GetJob(taskId);
+        if (task == null) throw new TaskNotFoundException(taskId);
+        if (ConfigManager.Instance.GetFreeCores() < task.CoresNeeded) throw new OutOfCoresException();
+        if (ConfigManager.GetFreeMemory() < task.MemoryNeeded) throw new OutOfMemoryException();
+        SlaveStatusInfo.IncrementUsedCores(task.CoresNeeded); usedCores = task.CoresNeeded;
+        TaskData taskData = wcfService.GetJobData(taskId);
+        if (taskData == null) throw new TaskDataNotFoundException(taskId);
+        task = wcfService.UpdateJobState(taskId, TaskState.Calculating, null);
+        if (task == null) throw new TaskNotFoundException(taskId);
+        taskManager.StartTaskAsync(task, taskData);
+      }
+      catch (TaskNotFoundException) {
         SlaveStatusInfo.DecrementUsedCores(usedCores);
         throw;
       }
-      catch (JobDataNotFoundException) {
+      catch (TaskDataNotFoundException) {
         SlaveStatusInfo.DecrementUsedCores(usedCores);
         throw;
       }
-      catch (JobAlreadyRunningException) {
+      catch (TaskAlreadyRunningException) {
         SlaveStatusInfo.DecrementUsedCores(usedCores);
         throw;
       }
       catch (OutOfCoresException) {
-        wcfService.UpdateJobState(jobId, TaskState.Waiting, "No more cores available");
+        wcfService.UpdateJobState(taskId, TaskState.Waiting, "No more cores available");
         throw;
       }
       catch (OutOfMemoryException) {
-        wcfService.UpdateJobState(jobId, TaskState.Waiting, "No more memory available");
+        wcfService.UpdateJobState(taskId, TaskState.Waiting, "No more memory available");
         throw;
       }
       catch (Exception e) {
         SlaveStatusInfo.DecrementUsedCores(usedCores);
-        wcfService.UpdateJobState(jobId, TaskState.Waiting, e.ToString()); // unknown internal error - report and set waiting again
-        throw;
-      }
-    }
-
-    private void HandleStopJob(object jobIdObj) {
-      Guid jobId = (Guid)jobIdObj;
-      try {
-        Task job = wcfService.GetJob(jobId);
-        if (job == null) throw new JobNotFoundException(jobId);
-        jobManager.StopJobAsync(jobId);
-      }
-      catch (JobNotFoundException) {
-        throw;
-      }
-      catch (JobNotRunningException) {
+        wcfService.UpdateJobState(taskId, TaskState.Waiting, e.ToString()); // unknown internal error - report and set waiting again
+        throw;
+      }
+    }
+
+    private void HandleStopTask(object taskIdObj) {
+      Guid taskId = (Guid)taskIdObj;
+      try {
+        Task task = wcfService.GetJob(taskId);
+        if (task == null) throw new TaskNotFoundException(taskId);
+        taskManager.StopTaskAsync(taskId);
+      }
+      catch (TaskNotFoundException) {
+        throw;
+      }
+      catch (TaskNotRunningException) {
         throw;
       }
@@ -288,15 +288,15 @@
     }
 
-    private void HandlePauseJob(object jobIdObj) {
-      Guid jobId = (Guid)jobIdObj;
-      try {
-        Task job = wcfService.GetJob(jobId);
-        if (job == null) throw new JobNotFoundException(jobId);
-        jobManager.PauseJobAsync(jobId);
-      }
-      catch (JobNotFoundException) {
-        throw;
-      }
-      catch (JobNotRunningException) {
+    private void HandlePauseTask(object taskIdObj) {
+      Guid taskId = (Guid)taskIdObj;
+      try {
+        Task task = wcfService.GetJob(taskId);
+        if (task == null) throw new TaskNotFoundException(taskId);
+        taskManager.PauseTaskAsync(taskId);
+      }
+      catch (TaskNotFoundException) {
+        throw;
+      }
+      catch (TaskNotRunningException) {
         throw;
       }
@@ -306,39 +306,39 @@
     }
 
-    private void HandleAbortJob(object jobIdObj) {
-      Guid jobId = (Guid)jobIdObj;
-      try {
-        jobManager.AbortJob(jobId);
-      }
-      catch (JobNotFoundException) {
-        throw;
-      }
-    }
-
-    #region JobManager Events
-    private void RegisterJobManagerEvents() {
-      this.jobManager.JobStarted += new EventHandler<EventArgs<SlaveJob>>(jobManager_JobStarted);
-      this.jobManager.JobPaused += new EventHandler<EventArgs<SlaveJob, TaskData>>(jobManager_JobPaused);
-      this.jobManager.JobStopped += new EventHandler<EventArgs<SlaveJob, TaskData>>(jobManager_JobStopped);
-      this.jobManager.JobFailed += new EventHandler<EventArgs<Tuple<SlaveJob, TaskData, Exception>>>(jobManager_JobFailed);
-      this.jobManager.ExceptionOccured += new EventHandler<EventArgs<SlaveJob, Exception>>(jobManager_ExceptionOccured);
-      this.jobManager.JobAborted += new EventHandler<EventArgs<SlaveJob>>(jobManager_JobAborted);
-    }
-
-    private void jobManager_JobStarted(object sender, EventArgs<SlaveJob> e) {
+    private void HandleAbortTask(object taskIdObj) {
+      Guid taskId = (Guid)taskIdObj;
+      try {
+        taskManager.AbortTask(taskId);
+      }
+      catch (TaskNotFoundException) {
+        throw;
+      }
+    }
+
+    #region TaskManager Events
+    private void RegisterTaskManagerEvents() {
+      this.taskManager.TaskStarted += new EventHandler<EventArgs<SlaveTask>>(taskManager_TaskStarted);
+      this.taskManager.TaskPaused += new EventHandler<EventArgs<SlaveTask, TaskData>>(taskManager_TaskPaused);
+      this.taskManager.TaskStopped += new EventHandler<EventArgs<SlaveTask, TaskData>>(taskManager_TaskStopped);
+      this.taskManager.TaskFailed += new EventHandler<EventArgs<Tuple<SlaveTask, TaskData, Exception>>>(taskManager_TaskFailed);
+      this.taskManager.ExceptionOccured += new EventHandler<EventArgs<SlaveTask, Exception>>(taskManager_ExceptionOccured);
+      this.taskManager.TaskAborted += new EventHandler<EventArgs<SlaveTask>>(taskManager_TaskAborted);
+    }
+
+    private void taskManager_TaskStarted(object sender, EventArgs<SlaveTask> e) {
       // successfully started, everything is good
     }
 
-    private void jobManager_JobPaused(object sender, EventArgs<SlaveJob, TaskData> e) {
+    private void taskManager_TaskPaused(object sender, EventArgs<SlaveTask, TaskData> e) {
       try {
         SlaveStatusInfo.DecrementUsedCores(e.Value.CoresNeeded);
         heartbeatManager.AwakeHeartBeatThread();
-        Task job = wcfService.GetJob(e.Value.JobId);
-        if (job == null) throw new JobNotFoundException(e.Value.JobId);
-        job.ExecutionTime = e.Value.ExecutionTime;
-        TaskData jobData = e.Value.GetJobData();
-        wcfService.UpdateJobData(job, jobData, configManager.GetClientInfo().Id, TaskState.Paused);
-      }
-      catch (JobNotFoundException ex) {
+        Task task = wcfService.GetJob(e.Value.TaskId);
+        if (task == null) throw new TaskNotFoundException(e.Value.TaskId);
+        task.ExecutionTime = e.Value.ExecutionTime;
+        TaskData taskData = e.Value.GetTaskData();
+        wcfService.UpdateJobData(task, taskData, configManager.GetClientInfo().Id, TaskState.Paused);
+      }
+      catch (TaskNotFoundException ex) {
         clientCom.LogMessage(ex.ToString());
       }
@@ -348,15 +348,15 @@
     }
 
-    private void jobManager_JobStopped(object sender, EventArgs<SlaveJob, TaskData> e) {
+    private void taskManager_TaskStopped(object sender, EventArgs<SlaveTask, TaskData> e) {
       try {
         SlaveStatusInfo.DecrementUsedCores(e.Value.CoresNeeded);
         heartbeatManager.AwakeHeartBeatThread();
-        Task job = wcfService.GetJob(e.Value.JobId);
-        if (job == null) throw new JobNotFoundException(e.Value.JobId);
-        job.ExecutionTime = e.Value.ExecutionTime;
-        TaskData jobData = e.Value.GetJobData();
-        wcfService.UpdateJobData(job, jobData, configManager.GetClientInfo().Id, TaskState.Finished);
-      }
-      catch (JobNotFoundException ex) {
+        Task task = wcfService.GetJob(e.Value.TaskId);
+        if (task == null) throw new TaskNotFoundException(e.Value.TaskId);
+        task.ExecutionTime = e.Value.ExecutionTime;
+        TaskData taskData = e.Value.GetTaskData();
+        wcfService.UpdateJobData(task, taskData, configManager.GetClientInfo().Id, TaskState.Finished);
+      }
+      catch (TaskNotFoundException ex) {
         clientCom.LogMessage(ex.ToString());
       }
@@ -366,23 +366,23 @@
     }
 
-    private void jobManager_JobFailed(object sender, EventArgs<Tuple<SlaveJob, TaskData, Exception>> e) {
+    private void taskManager_TaskFailed(object sender, EventArgs<Tuple<SlaveTask, TaskData, Exception>> e) {
       try {
         SlaveStatusInfo.DecrementUsedCores(e.Value.Item1.CoresNeeded);
         heartbeatManager.AwakeHeartBeatThread();
-        SlaveJob slaveJob = e.Value.Item1;
-        TaskData jobData = e.Value.Item2;
+        SlaveTask slaveTask = e.Value.Item1;
+        TaskData taskData = e.Value.Item2;
         Exception exception = e.Value.Item3;
 
-        Task job = wcfService.GetJob(slaveJob.JobId);
-        if (job == null) throw new JobNotFoundException(slaveJob.JobId);
-        job.ExecutionTime = slaveJob.ExecutionTime;
-        if (jobData != null) {
-          wcfService.UpdateJobData(job, jobData, configManager.GetClientInfo().Id, TaskState.Failed, exception.ToString());
+        Task task = wcfService.GetJob(slaveTask.TaskId);
+        if (task == null) throw new TaskNotFoundException(slaveTask.TaskId);
+        task.ExecutionTime = slaveTask.ExecutionTime;
+        if (taskData != null) {
+          wcfService.UpdateJobData(task, taskData, configManager.GetClientInfo().Id, TaskState.Failed, exception.ToString());
         } else {
-          wcfService.UpdateJobState(job.Id, TaskState.Failed, exception.ToString());
+          wcfService.UpdateJobState(task.Id, TaskState.Failed, exception.ToString());
         }
         clientCom.LogMessage(exception.Message);
       }
-      catch (JobNotFoundException ex) {
+      catch (TaskNotFoundException ex) {
         SlaveStatusInfo.IncrementExceptionOccured();
         clientCom.LogMessage(ex.ToString());
@@ -394,13 +394,13 @@
     }
 
-    private void jobManager_ExceptionOccured(object sender, EventArgs<SlaveJob, Exception> e) {
+    private void taskManager_ExceptionOccured(object sender, EventArgs<SlaveTask, Exception> e) {
       SlaveStatusInfo.DecrementUsedCores(e.Value.CoresNeeded);
       SlaveStatusInfo.IncrementExceptionOccured();
       heartbeatManager.AwakeHeartBeatThread();
-      clientCom.LogMessage(string.Format("Exception occured for job {0}: {1}", e.Value.JobId, e.Value2.ToString()));
-      wcfService.UpdateJobState(e.Value.JobId, TaskState.Waiting, e.Value2.ToString());
-    }
-
-    private void jobManager_JobAborted(object sender, EventArgs<SlaveJob> e) {
+      clientCom.LogMessage(string.Format("Exception occured for task {0}: {1}", e.Value.TaskId, e.Value2.ToString()));
+      wcfService.UpdateJobState(e.Value.TaskId, TaskState.Waiting, e.Value2.ToString());
+    }
+
+    private void taskManager_TaskAborted(object sender, EventArgs<SlaveTask> e) {
       SlaveStatusInfo.DecrementUsedCores(e.Value.CoresNeeded);
     }
@@ -418,6 +418,6 @@
     private void DoAbortAll() {
       clientCom.LogMessage("Aborting all jobs.");
-      foreach (Guid jobId in jobManager.JobIds) {
-        AbortJobAsync(jobId);
+      foreach (Guid taskId in taskManager.TaskIds) {
+        AbortTaskAsync(taskId);
       }
     }
@@ -428,6 +428,6 @@
     private void DoPauseAll() {
       clientCom.LogMessage("Pausing all jobs.");
-      foreach (Guid jobId in jobManager.JobIds) {
-        PauseJobAsync(jobId);
+      foreach (Guid taskId in taskManager.TaskIds) {
+        PauseTaskAsync(taskId);
       }
     }
@@ -438,6 +438,6 @@
     private void DoStopAll() {
       clientCom.LogMessage("Stopping all jobs.");
-      foreach (Guid jobId in jobManager.JobIds) {
-        StopJobAsync(jobId);
+      foreach (Guid taskId in taskManager.TaskIds) {
+        StopTaskAsync(taskId);
       }
     }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/AppDomainNotCreatedException.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/AppDomainNotCreatedException.cs	(revision 6725)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/AppDomainNotCreatedException.cs	(revision 6725)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+
+namespace HeuristicLab.Clients.Hive.SlaveCore {
+  public class AppDomainNotCreatedException : Exception {
+    public AppDomainNotCreatedException() : base("AppDomain has not been created.") { }
+  }
+}
+
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/JobAlreadyRunningException.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/JobAlreadyRunningException.cs	(revision 6723)
+++ 	(revision )
@@ -1,28 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-
-namespace HeuristicLab.Clients.Hive.SlaveCore {
-  public class JobAlreadyRunningException : Exception {
-    public JobAlreadyRunningException(Guid jobId) : base(string.Format("Task with Id {0} is already running.", jobId)) { }
-  }
-}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/JobFailedException.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/JobFailedException.cs	(revision 6723)
+++ 	(revision )
@@ -1,28 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-
-namespace HeuristicLab.Clients.Hive.SlaveCore {
-  public class JobFailedException : Exception {
-    public JobFailedException(string reason) : base(string.Format("Task failed with reason: {0}", reason)) { }
-  }
-}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/JobNotDataFoundException.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/JobNotDataFoundException.cs	(revision 6723)
+++ 	(revision )
@@ -1,28 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-
-namespace HeuristicLab.Clients.Hive.SlaveCore {
-  public class JobDataNotFoundException : Exception {
-    public JobDataNotFoundException(Guid jobId) : base(string.Format("TaskData with TaskId {0} was not found on server.", jobId)) { }
-  }
-}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/JobNotFoundException.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/JobNotFoundException.cs	(revision 6723)
+++ 	(revision )
@@ -1,28 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-
-namespace HeuristicLab.Clients.Hive.SlaveCore {
-  public class JobNotFoundException : Exception {
-    public JobNotFoundException(Guid jobId) : base (string.Format("Task with Id {0} was not found on server.", jobId)) { }
-  }
-}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/JobNotRunningException.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/JobNotRunningException.cs	(revision 6723)
+++ 	(revision )
@@ -1,28 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-
-namespace HeuristicLab.Clients.Hive.SlaveCore {
-  public class JobNotRunningException : Exception {
-    public JobNotRunningException(Guid jobId) : base(string.Format("Task with Id {0} is not running.", jobId)) { }
-  }
-}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/JobNotStartedException.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/JobNotStartedException.cs	(revision 6723)
+++ 	(revision )
@@ -1,29 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-
-namespace HeuristicLab.Clients.Hive.SlaveCore {
-  public class AppDomainNotCreatedException : Exception {
-    public AppDomainNotCreatedException() : base("AppDomain has not been created.") { }
-  }
-}
-
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/SerializationException.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/SerializationException.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/SerializationException.cs	(revision 6725)
@@ -24,5 +24,5 @@
 namespace HeuristicLab.Clients.Hive.SlaveCore {
   public class SerializationException : Exception {
-    public SerializationException() : base("Serializing job failed.") { }
+    public SerializationException() : base("Serializing task failed.") { }
   }
 }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/TaskAlreadyRunningException.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/TaskAlreadyRunningException.cs	(revision 6725)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/TaskAlreadyRunningException.cs	(revision 6725)
@@ -0,0 +1,28 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+
+namespace HeuristicLab.Clients.Hive.SlaveCore {
+  public class TaskAlreadyRunningException : Exception {
+    public TaskAlreadyRunningException(Guid jobId) : base(string.Format("Task with Id {0} is already running.", jobId)) { }
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/TaskFailedException.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/TaskFailedException.cs	(revision 6725)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/TaskFailedException.cs	(revision 6725)
@@ -0,0 +1,28 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+
+namespace HeuristicLab.Clients.Hive.SlaveCore {
+  public class TaskFailedException : Exception {
+    public TaskFailedException(string reason) : base(string.Format("Task failed with reason: {0}", reason)) { }
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/TaskNotDataFoundException.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/TaskNotDataFoundException.cs	(revision 6725)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/TaskNotDataFoundException.cs	(revision 6725)
@@ -0,0 +1,28 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+
+namespace HeuristicLab.Clients.Hive.SlaveCore {
+  public class TaskDataNotFoundException : Exception {
+    public TaskDataNotFoundException(Guid jobId) : base(string.Format("TaskData with TaskId {0} was not found on server.", jobId)) { }
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/TaskNotFoundException.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/TaskNotFoundException.cs	(revision 6725)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/TaskNotFoundException.cs	(revision 6725)
@@ -0,0 +1,28 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+
+namespace HeuristicLab.Clients.Hive.SlaveCore {
+  public class TaskNotFoundException : Exception {
+    public TaskNotFoundException(Guid jobId) : base (string.Format("Task with Id {0} was not found on server.", jobId)) { }
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/TaskNotRunningException.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/TaskNotRunningException.cs	(revision 6725)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Exceptions/TaskNotRunningException.cs	(revision 6725)
@@ -0,0 +1,28 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+
+namespace HeuristicLab.Clients.Hive.SlaveCore {
+  public class TaskNotRunningException : Exception {
+    public TaskNotRunningException(Guid jobId) : base(string.Format("Task with Id {0} is not running.", jobId)) { }
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Executor.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Executor.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Executor.cs	(revision 6725)
@@ -29,17 +29,17 @@
 namespace HeuristicLab.Clients.Hive.SlaveCore {
   /// <summary>
-  /// The executor runs in the appdomain and handles the execution of an Hive job.
+  /// The executor runs in the appdomain and handles the execution of an Hive task.
   /// </summary>
   public class Executor : MarshalByRefObject, IDisposable {
-    private bool wasJobAborted = false;
+    private bool wasTaskAborted = false;
     private AutoResetEvent pauseStopSem = new AutoResetEvent(false);
-    private AutoResetEvent startJobSem = new AutoResetEvent(false); // block start method call
-    private AutoResetEvent jobStartedSem = new AutoResetEvent(false); // make pause or stop wait until start is finished
+    private AutoResetEvent startTaskSem = new AutoResetEvent(false); // block start method call
+    private AutoResetEvent taskStartedSem = new AutoResetEvent(false); // make pause or stop wait until start is finished
     private ExecutorQueue executorQueue;
-    private bool jobDataInvalid = false; // if true, the jobdata is not sent when the job is failed
-    private IJob job;
+    private bool taskDataInvalid = false; // if true, the jobdata is not sent when the task is failed
+    private ITask task;
     private DateTime creationTime;
 
-    public Guid JobId { get; set; }
+    public Guid TaskId { get; set; }
     public int CoresNeeded { get; set; }
     public int MemoryNeeded { get; set; }
@@ -63,9 +63,9 @@
 
     private ExecutionState ExecutionState {
-      get { return job != null ? job.ExecutionState : HeuristicLab.Core.ExecutionState.Stopped; }
+      get { return task != null ? task.ExecutionState : HeuristicLab.Core.ExecutionState.Stopped; }
     }
 
     public TimeSpan ExecutionTime {
-      get { return job != null ? job.ExecutionTime : new TimeSpan(0, 0, 0); }
+      get { return task != null ? task.ExecutionTime : new TimeSpan(0, 0, 0); }
     }
 
@@ -79,20 +79,20 @@
       try {
         creationTime = DateTime.Now;
-        job = PersistenceUtil.Deserialize<IJob>(serializedJob);
+        task = PersistenceUtil.Deserialize<ITask>(serializedJob);
 
         RegisterJobEvents();
 
-        job.Start();
-        if (!startJobSem.WaitOne(Settings.Default.ExecutorSemTimeouts)) {
-          jobDataInvalid = true;
-          throw new TimeoutException("Timeout when starting the job. JobStarted event was not fired.");
+        task.Start();
+        if (!startTaskSem.WaitOne(Settings.Default.ExecutorSemTimeouts)) {
+          taskDataInvalid = true;
+          throw new TimeoutException("Timeout when starting the task. TaskStarted event was not fired.");
         }
       }
       catch (Exception e) {
         this.CurrentException = e;
-        Job_JobFailed(this, new EventArgs<Exception>(e));
+        Task_TaskFailed(this, new EventArgs<Exception>(e));
       }
       finally {
-        jobStartedSem.Set();
+        taskStartedSem.Set();
       }
     }
@@ -100,20 +100,20 @@
     public void Pause() {
       IsPausing = true;
-      // wait until job is started. if this does not happen, the Task is null an we give up
-      jobStartedSem.WaitOne(Settings.Default.ExecutorSemTimeouts);
-      if (job == null) {
-        CurrentException = new Exception("Pausing job " + this.JobId + ": Task is null");
+      // wait until task is started. if this does not happen, the Task is null an we give up
+      taskStartedSem.WaitOne(Settings.Default.ExecutorSemTimeouts);
+      if (task == null) {
+        CurrentException = new Exception("Pausing task " + this.TaskId + ": Task is null");
         executorQueue.AddMessage(ExecutorMessageType.ExceptionOccured);
         return;
       }
 
-      if (job.ExecutionState == ExecutionState.Started) {
+      if (task.ExecutionState == ExecutionState.Started) {
         try {
-          job.Pause();
+          task.Pause();
           //we need to block the pause...
           pauseStopSem.WaitOne();
         }
         catch (Exception ex) {
-          CurrentException = new Exception("Error pausing job " + this.JobId + ": " + ex.ToString());
+          CurrentException = new Exception("Error pausing task " + this.TaskId + ": " + ex.ToString());
           executorQueue.AddMessage(ExecutorMessageType.ExceptionOccured);
         }
@@ -123,19 +123,19 @@
     public void Stop() {
       IsStopping = true;
-      // wait until job is started. if this does not happen, the Task is null an we give up
-      jobStartedSem.WaitOne(Settings.Default.ExecutorSemTimeouts);
-      if (job == null) {
-        CurrentException = new Exception("Stopping job " + this.JobId + ": Task is null");
+      // wait until task is started. if this does not happen, the Task is null an we give up
+      taskStartedSem.WaitOne(Settings.Default.ExecutorSemTimeouts);
+      if (task == null) {
+        CurrentException = new Exception("Stopping task " + this.TaskId + ": Task is null");
         executorQueue.AddMessage(ExecutorMessageType.ExceptionOccured);
       }
-      wasJobAborted = true;
+      wasTaskAborted = true;
 
       if ((ExecutionState == ExecutionState.Started) || (ExecutionState == ExecutionState.Paused)) {
         try {
-          job.Stop();
+          task.Stop();
           pauseStopSem.WaitOne();
         }
         catch (Exception ex) {
-          CurrentException = new Exception("Error stopping job " + this.JobId + ": " + ex.ToString());
+          CurrentException = new Exception("Error stopping task " + this.TaskId + ": " + ex.ToString());
           executorQueue.AddMessage(ExecutorMessageType.ExceptionOccured);
         }
@@ -144,70 +144,70 @@
 
     private void RegisterJobEvents() {
-      job.JobStopped += new EventHandler(Job_JobStopped);
-      job.JobFailed += new EventHandler(Job_JobFailed);
-      job.JobPaused += new EventHandler(Job_JobPaused);
-      job.JobStarted += new EventHandler(Job_JobStarted);
+      task.TaskStopped += new EventHandler(Task_TaskStopped);
+      task.TaskFailed += new EventHandler(Task_TaskFailed);
+      task.TaskPaused += new EventHandler(Task_TaskPaused);
+      task.TaskStarted += new EventHandler(Task_TaskStarted);
     }
 
     private void DeregisterJobEvents() {
-      job.JobStopped -= new EventHandler(Job_JobStopped);
-      job.JobFailed -= new EventHandler(Job_JobFailed);
-      job.JobPaused -= new EventHandler(Job_JobPaused);
-      job.JobStarted -= new EventHandler(Job_JobStarted);
+      task.TaskStopped -= new EventHandler(Task_TaskStopped);
+      task.TaskFailed -= new EventHandler(Task_TaskFailed);
+      task.TaskPaused -= new EventHandler(Task_TaskPaused);
+      task.TaskStarted -= new EventHandler(Task_TaskStarted);
     }
 
     #region Task Events
-    private void Job_JobFailed(object sender, EventArgs e) {
+    private void Task_TaskFailed(object sender, EventArgs e) {
       IsStopping = true;
       EventArgs<Exception> ex = (EventArgs<Exception>)e;
       CurrentException = ex.Value;
-      executorQueue.AddMessage(ExecutorMessageType.JobFailed);
-    }
-
-    private void Job_JobStopped(object sender, EventArgs e) {
+      executorQueue.AddMessage(ExecutorMessageType.TaskFailed);
+    }
+
+    private void Task_TaskStopped(object sender, EventArgs e) {
       IsStopping = true;
-      if (wasJobAborted) {
+      if (wasTaskAborted) {
         pauseStopSem.Set();
       }
-      executorQueue.AddMessage(ExecutorMessageType.JobStopped);
-    }
-
-    private void Job_JobPaused(object sender, EventArgs e) {
+      executorQueue.AddMessage(ExecutorMessageType.TaskStopped);
+    }
+
+    private void Task_TaskPaused(object sender, EventArgs e) {
       IsPausing = true;
       pauseStopSem.Set();
-      executorQueue.AddMessage(ExecutorMessageType.JobPaused);
-    }
-
-    private void Job_JobStarted(object sender, EventArgs e) {
-      startJobSem.Set();
-      executorQueue.AddMessage(ExecutorMessageType.JobStarted);
+      executorQueue.AddMessage(ExecutorMessageType.TaskPaused);
+    }
+
+    private void Task_TaskStarted(object sender, EventArgs e) {
+      startTaskSem.Set();
+      executorQueue.AddMessage(ExecutorMessageType.TaskStarted);
     }
     #endregion
 
-    public TaskData GetJobData() {
-      if (jobDataInvalid) return null;
-
-      if (job.ExecutionState == ExecutionState.Started) {
+    public TaskData GetTaskData() {
+      if (taskDataInvalid) return null;
+
+      if (task.ExecutionState == ExecutionState.Started) {
         throw new InvalidStateException("Task is still running");
       } else {
-        TaskData jobData = new TaskData();
-        if (job == null) {
-          //send empty job and save exception
-          jobData.Data = PersistenceUtil.Serialize(new TaskData());
+        TaskData taskData = new TaskData();
+        if (task == null) {
+          //send empty task and save exception
+          taskData.Data = PersistenceUtil.Serialize(new TaskData());
           if (CurrentException == null) {
-            CurrentException = new Exception("Task with id " + this.JobId + " is null, sending empty job");
+            CurrentException = new Exception("Task with id " + this.TaskId + " is null, sending empty task");
           }
         } else {
-          jobData.Data = PersistenceUtil.Serialize(job);
-        }
-        jobData.TaskId = JobId;
-        return jobData;
+          taskData.Data = PersistenceUtil.Serialize(task);
+        }
+        taskData.TaskId = TaskId;
+        return taskData;
       }
     }
 
     public void Dispose() {
-      if (job != null)
+      if (task != null)
         DeregisterJobEvents();
-      job = null;
+      task = null;
     }
   }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/ExecutorMessage.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/ExecutorMessage.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/ExecutorMessage.cs	(revision 6725)
@@ -26,8 +26,8 @@
   [Serializable]
   public enum ExecutorMessageType {
-    JobStarted,
-    JobPaused,
-    JobStopped,
-    JobFailed,
+    TaskStarted,
+    TaskPaused,
+    TaskStopped,
+    TaskFailed,
     StopExecutorMonitoringThread,
     ExceptionOccured
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/HeuristicLab.Clients.Hive.Slave-3.3.csproj
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/HeuristicLab.Clients.Hive.Slave-3.3.csproj	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/HeuristicLab.Clients.Hive.Slave-3.3.csproj	(revision 6725)
@@ -101,18 +101,18 @@
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="Exceptions\JobFailedException.cs" />
+    <Compile Include="Exceptions\TaskFailedException.cs" />
     <Compile Include="Manager\ConfigManager.cs" />
     <Compile Include="Exceptions\SerializationException.cs" />
     <Compile Include="Exceptions\OutOfMemoryException.cs" />
-    <Compile Include="Exceptions\JobNotRunningException.cs" />
-    <Compile Include="Exceptions\JobAlreadyRunningException.cs" />
-    <Compile Include="Exceptions\JobNotFoundException.cs" />
-    <Compile Include="Exceptions\JobNotDataFoundException.cs" />
+    <Compile Include="Exceptions\TaskNotRunningException.cs" />
+    <Compile Include="Exceptions\TaskAlreadyRunningException.cs" />
+    <Compile Include="Exceptions\TaskNotFoundException.cs" />
+    <Compile Include="Exceptions\TaskNotDataFoundException.cs" />
     <Compile Include="ExecutorMessage.cs" />
     <Compile Include="ExecutorQueue.cs" />
     <Compile Include="IPluginProvider.cs" />
-    <Compile Include="Manager\JobManager.cs" />
+    <Compile Include="Manager\TaskManager.cs" />
     <Compile Include="Exceptions\OutOfCoresException.cs" />
-    <Compile Include="Exceptions\JobNotStartedException.cs" />
+    <Compile Include="Exceptions\AppDomainNotCreatedException.cs" />
     <Compile Include="SlaveClientCom.cs" />
     <Compile Include="Core.cs" />
@@ -121,5 +121,5 @@
     <Compile Include="Manager\HeartbeatManager.cs" />
     <Compile Include="Exceptions\InvalidStateException.cs" />
-    <Compile Include="JobStatus.cs" />
+    <Compile Include="TaskStatus.cs" />
     <Compile Include="MessageQueue.cs" />
     <Compile Include="NetworkEnum.cs" />
@@ -133,5 +133,5 @@
     <Compile Include="ServiceContracts\ISlaveCommunicationCallbacks.cs" />
     <Compile Include="SlaveCommunicationService.cs" />
-    <Compile Include="SlaveJob.cs" />
+    <Compile Include="SlaveTask.cs" />
     <Compile Include="SlaveStatusInfo.cs" />
     <Compile Include="StatusCommons.cs" />
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/JobStatus.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/JobStatus.cs	(revision 6723)
+++ 	(revision )
@@ -1,39 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-using System.Runtime.Serialization;
-
-namespace HeuristicLab.Clients.Hive.SlaveCore {
-  [DataContract]
-  public class JobStatus {
-    /// <summary>
-    /// Id of the Task
-    /// </summary>
-    [DataMember]
-    public Guid JobId { get; set; }
-    /// <summary>
-    /// Current progress
-    /// </summary>
-    [DataMember]
-    public TimeSpan ExecutionTime { get; set; }
-  }
-}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Manager/ConfigManager.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Manager/ConfigManager.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Manager/ConfigManager.cs	(revision 6725)
@@ -42,5 +42,5 @@
     /// </summary>
     public bool Asleep { get; set; }
-    private JobManager jobManager;
+    private TaskManager jobManager;
     private Slave slave;
     private PerformanceCounter cpuCounter;
@@ -49,5 +49,5 @@
     /// Constructor for the singleton, must recover Guid, Calendar, ...
     /// </summary>
-    public ConfigManager(JobManager jobManager) {
+    public ConfigManager(TaskManager jobManager) {
       this.jobManager = jobManager;
       cpuCounter = new PerformanceCounter();
@@ -95,12 +95,12 @@
       st.Asleep = this.Asleep;
 
-      st.JobsStarted = SlaveStatusInfo.JobsStarted;
-      st.JobsAborted = SlaveStatusInfo.JobsAborted;
-      st.JobsFinished = SlaveStatusInfo.JobsFinished;
-      st.JobsFetched = SlaveStatusInfo.JobsFetched;
-      st.JobsFailed = SlaveStatusInfo.JobsFailed;
+      st.JobsStarted = SlaveStatusInfo.TasksStarted;
+      st.JobsAborted = SlaveStatusInfo.TasksAborted;
+      st.JobsFinished = SlaveStatusInfo.TasksFinished;
+      st.JobsFetched = SlaveStatusInfo.TasksFetched;
+      st.JobsFailed = SlaveStatusInfo.TasksFailed;
       st.ExceptionsOccured = SlaveStatusInfo.ExceptionsOccured;
 
-      st.Jobs = jobManager.GetExecutionTimes().Select(x => new JobStatus { JobId = x.Key, ExecutionTime = x.Value }).ToList();
+      st.Jobs = jobManager.GetExecutionTimes().Select(x => new TaskStatus { TaskId = x.Key, ExecutionTime = x.Value }).ToList();
 
       return st;
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Manager/JobManager.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Manager/JobManager.cs	(revision 6723)
+++ 	(revision )
@@ -1,335 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using HeuristicLab.Common;
-using HeuristicLab.Core;
-
-namespace HeuristicLab.Clients.Hive.SlaveCore {
-
-  /// <summary>
-  /// Holds a list of slave jobs and manages access to this list. 
-  /// Forwards events from SlaveJob and forwards commands to SlaveJob. 
-  /// </summary>
-  public class JobManager {
-    private static ReaderWriterLockSlim slaveJobsLocker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
-    private Dictionary<Guid, SlaveJob> slaveJobs;
-    private ILog log;
-    private PluginManager pluginManager;
-
-    public int JobCount {
-      get {
-        slaveJobsLocker.EnterReadLock();
-        try {
-          return slaveJobs.Count;
-        }
-        finally { slaveJobsLocker.ExitReadLock(); }
-      }
-    }
-
-    public Guid[] JobIds {
-      get {
-        slaveJobsLocker.EnterReadLock();
-        try {
-          return slaveJobs.Keys.ToArray();
-        }
-        finally { slaveJobsLocker.ExitReadLock(); }
-      }
-    }
-
-    public JobManager(PluginManager pluginCache, ILog log) {
-      this.pluginManager = pluginCache;
-      this.log = log;
-      this.slaveJobs = new Dictionary<Guid, SlaveJob>();
-    }
-
-    #region Task Control methods
-    public void StartJobAsync(Task job, TaskData jobData) {
-      SlaveJob slaveJob = null;
-      slaveJobsLocker.EnterUpgradeableReadLock();
-      try {
-        if (slaveJobs.ContainsKey(job.Id)) {
-          SlaveStatusInfo.IncrementExceptionOccured();
-          throw new JobAlreadyRunningException(job.Id);
-        } else {
-          slaveJob = new SlaveJob(pluginManager, job.CoresNeeded, log);
-          AddSlaveJob(job, slaveJob);
-          SlaveStatusInfo.IncrementJobsFetched();
-        }
-      }
-      finally { slaveJobsLocker.ExitUpgradeableReadLock(); }
-
-      if (slaveJob != null) {
-        try {
-          slaveJob.StartJobAsync(job, jobData);
-        }
-        catch (Exception) {
-          RemoveSlaveJob(job.Id, slaveJob); // clean up and rethrow
-          slaveJob.DisposeAppDomain();
-          throw;
-        }
-      }
-    }
-
-    public void PauseJobAsync(Guid jobId) {
-      slaveJobsLocker.EnterUpgradeableReadLock();
-      try {
-        if (!slaveJobs.ContainsKey(jobId)) throw new JobNotRunningException(jobId);
-        SlaveJob slaveJob = slaveJobs[jobId];
-        slaveJob.PauseJob();
-      }
-      finally { slaveJobsLocker.ExitUpgradeableReadLock(); }
-    }
-
-    public void StopJobAsync(Guid jobId) {
-      slaveJobsLocker.EnterUpgradeableReadLock();
-      try {
-        if (!slaveJobs.ContainsKey(jobId)) throw new JobNotRunningException(jobId);
-        SlaveJob slaveJob = slaveJobs[jobId];
-        slaveJob.StopJob();
-      }
-      finally { slaveJobsLocker.ExitUpgradeableReadLock(); }
-    }
-
-    public void AbortJob(Guid jobId) {
-      SlaveJob slaveJob = null;
-      slaveJobsLocker.EnterUpgradeableReadLock();
-      try {
-        if (!slaveJobs.ContainsKey(jobId)) throw new JobNotRunningException(jobId);
-        slaveJob = slaveJobs[jobId];
-        if (!slaveJob.IsPrepared) throw new AppDomainNotCreatedException();
-        RemoveSlaveJob(jobId, slaveJob);
-      }
-      finally { slaveJobsLocker.ExitUpgradeableReadLock(); }
-      slaveJob.DisposeAppDomain();
-      SlaveStatusInfo.IncrementJobsAborted();
-      OnJobAborted(slaveJob);
-    }
-
-    public void PauseAllJobsAsync() {
-      slaveJobsLocker.EnterUpgradeableReadLock();
-      try {
-        foreach (var slaveJob in slaveJobs.Values) {
-          slaveJob.PauseJob();
-        }
-      }
-      finally { slaveJobsLocker.ExitUpgradeableReadLock(); }
-    }
-
-    public void StopAllJobsAsync() {
-      slaveJobsLocker.EnterUpgradeableReadLock();
-      try {
-        foreach (var slaveJob in slaveJobs.Values) {
-          slaveJob.StopJob();
-        }
-      }
-      finally { slaveJobsLocker.ExitUpgradeableReadLock(); }
-    }
-
-    public void AbortAllJobs() {
-      slaveJobsLocker.EnterUpgradeableReadLock();
-      try {
-        foreach (var slaveJob in slaveJobs.Values.ToArray()) {
-          AbortJob(slaveJob.JobId);
-        }
-      }
-      finally { slaveJobsLocker.ExitUpgradeableReadLock(); }
-    }
-    #endregion
-
-    #region Add/Remove SlaveJob
-    private void AddSlaveJob(Task job, SlaveJob slaveJob) {
-      slaveJobsLocker.EnterWriteLock();
-      try {
-        slaveJobs.Add(job.Id, slaveJob);
-        RegisterSlaveJobEvents(slaveJob);
-      }
-      finally { slaveJobsLocker.ExitWriteLock(); }
-    }
-
-    private void RemoveSlaveJob(Guid jobId, SlaveJob slaveJob) {
-      slaveJobsLocker.EnterWriteLock();
-      try {
-        slaveJobs.Remove(jobId);
-        DeregisterSlaveJobEvents(slaveJob);
-      }
-      finally { slaveJobsLocker.ExitWriteLock(); }
-    }
-    #endregion
-
-    #region SlaveJob Events
-    private void RegisterSlaveJobEvents(SlaveJob slaveJob) {
-      slaveJob.JobStarted += new EventHandler<EventArgs<Guid>>(slaveJob_JobStarted);
-      slaveJob.JobPaused += new EventHandler<EventArgs<Guid>>(slaveJob_JobPaused);
-      slaveJob.JobStopped += new EventHandler<EventArgs<Guid>>(slaveJob_JobStopped);
-      slaveJob.JobFailed += new EventHandler<EventArgs<Guid, Exception>>(slaveJob_JobFailed);
-      slaveJob.ExceptionOccured += new EventHandler<EventArgs<Guid, Exception>>(slaveJob_ExceptionOccured);
-    }
-
-    private void DeregisterSlaveJobEvents(SlaveJob slaveJob) {
-      slaveJob.JobStarted -= new EventHandler<EventArgs<Guid>>(slaveJob_JobStarted);
-      slaveJob.JobPaused -= new EventHandler<EventArgs<Guid>>(slaveJob_JobPaused);
-      slaveJob.JobStopped -= new EventHandler<EventArgs<Guid>>(slaveJob_JobStopped);
-      slaveJob.JobFailed -= new EventHandler<EventArgs<Guid, Exception>>(slaveJob_JobFailed);
-      slaveJob.ExceptionOccured -= new EventHandler<EventArgs<Guid, Exception>>(slaveJob_ExceptionOccured);
-    }
-
-    private void slaveJob_JobStarted(object sender, EventArgs<Guid> e) {
-      SlaveJob slaveJob;
-      slaveJobsLocker.EnterUpgradeableReadLock();
-      try {
-        slaveJob = slaveJobs[e.Value];
-      }
-      finally { slaveJobsLocker.ExitUpgradeableReadLock(); }
-
-      SlaveStatusInfo.IncrementJobsStarted();
-      OnJobStarted(slaveJob);
-    }
-
-    private void slaveJob_JobPaused(object sender, EventArgs<Guid> e) {
-      SlaveJob slaveJob;
-      slaveJobsLocker.EnterUpgradeableReadLock();
-      try {
-        slaveJob = slaveJobs[e.Value];
-        RemoveSlaveJob(e.Value, slaveJob);
-      }
-      finally { slaveJobsLocker.ExitUpgradeableReadLock(); }
-
-      TaskData jobData = null;
-      try {
-        jobData = slaveJob.GetJobData();
-        if (jobData == null) throw new SerializationException();
-        SlaveStatusInfo.IncrementJobsFinished();
-        OnJobPaused(slaveJob, jobData);
-      }
-      catch (Exception ex) {
-        RemoveSlaveJob(e.Value, slaveJob);
-        SlaveStatusInfo.IncrementJobsFailed();
-        OnJobFailed(slaveJob, jobData, ex);
-      }
-    }
-
-    private void slaveJob_JobStopped(object sender, EventArgs<Guid> e) {
-      SlaveJob slaveJob;
-      slaveJobsLocker.EnterUpgradeableReadLock();
-      try {
-        slaveJob = slaveJobs[e.Value];
-        RemoveSlaveJob(e.Value, slaveJob);
-      }
-      finally { slaveJobsLocker.ExitUpgradeableReadLock(); }
-
-      TaskData jobData = null;
-      try {
-        jobData = slaveJob.GetJobData();
-        if (jobData == null) throw new SerializationException();
-        SlaveStatusInfo.IncrementJobsFinished();
-        OnJobStopped(slaveJob, jobData);
-      }
-      catch (Exception ex) {
-        RemoveSlaveJob(e.Value, slaveJob);
-        SlaveStatusInfo.IncrementJobsFailed();
-        OnJobFailed(slaveJob, jobData, ex);
-      }
-    }
-
-    private void slaveJob_JobFailed(object sender, EventArgs<Guid, Exception> e) {
-      SlaveJob slaveJob;
-      slaveJobsLocker.EnterUpgradeableReadLock();
-      try {
-        slaveJob = slaveJobs[e.Value];
-        RemoveSlaveJob(e.Value, slaveJob);
-      }
-      finally { slaveJobsLocker.ExitUpgradeableReadLock(); }
-
-      TaskData jobData = null;
-      try {
-        jobData = slaveJob.GetJobData();
-        if (jobData == null) throw new SerializationException();
-      }
-      catch { /* jobData will be null */ }
-      SlaveStatusInfo.IncrementJobsFailed();
-      OnJobFailed(slaveJob, jobData, e.Value2);
-    }
-
-    private void slaveJob_ExceptionOccured(object sender, EventArgs<Guid, Exception> e) {
-      SlaveJob slaveJob;
-      slaveJobsLocker.EnterUpgradeableReadLock();
-      try {
-        slaveJob = slaveJobs[e.Value];
-        RemoveSlaveJob(e.Value, slaveJob);
-      }
-      finally { slaveJobsLocker.ExitUpgradeableReadLock(); }
-
-      SlaveStatusInfo.IncrementExceptionOccured();
-      OnExceptionOccured(slaveJob, e.Value2);
-    }
-    #endregion
-
-    #region EventHandler
-    public event EventHandler<EventArgs<SlaveJob>> JobStarted;
-    private void OnJobStarted(SlaveJob slaveJob) {
-      var handler = JobStarted;
-      if (handler != null) handler(this, new EventArgs<SlaveJob>(slaveJob));
-    }
-
-    public event EventHandler<EventArgs<SlaveJob, TaskData>> JobStopped;
-    private void OnJobStopped(SlaveJob slaveJob, TaskData jobData) {
-      var handler = JobStopped;
-      if (handler != null) handler(this, new EventArgs<SlaveJob, TaskData>(slaveJob, jobData));
-    }
-
-    public event EventHandler<EventArgs<SlaveJob, TaskData>> JobPaused;
-    private void OnJobPaused(SlaveJob slaveJob, TaskData jobData) {
-      var handler = JobPaused;
-      if (handler != null) handler(this, new EventArgs<SlaveJob, TaskData>(slaveJob, jobData));
-    }
-
-    public event EventHandler<EventArgs<Tuple<SlaveJob, TaskData, Exception>>> JobFailed;
-    private void OnJobFailed(SlaveJob slaveJob, TaskData jobData, Exception exception) {
-      var handler = JobFailed;
-      if (handler != null) handler(this, new EventArgs<Tuple<SlaveJob, TaskData, Exception>>(new Tuple<SlaveJob, TaskData, Exception>(slaveJob, jobData, exception)));
-    }
-
-    public event EventHandler<EventArgs<SlaveJob, Exception>> ExceptionOccured;
-    private void OnExceptionOccured(SlaveJob slaveJob, Exception exception) {
-      var handler = ExceptionOccured;
-      if (handler != null) handler(this, new EventArgs<SlaveJob, Exception>(slaveJob, exception));
-    }
-
-    public event EventHandler<EventArgs<SlaveJob>> JobAborted;
-    private void OnJobAborted(SlaveJob slaveJob) {
-      var handler = JobAborted;
-      if (handler != null) handler(this, new EventArgs<SlaveJob>(slaveJob));
-    }
-    #endregion
-
-    public Dictionary<Guid, TimeSpan> GetExecutionTimes() {
-      slaveJobsLocker.EnterReadLock();
-      try {
-        return slaveJobs.ToDictionary(x => x.Key, x => x.Value.ExecutionTime);
-      }
-      finally { slaveJobsLocker.ExitReadLock(); }
-    }
-  }
-}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Manager/PluginManager.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Manager/PluginManager.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Manager/PluginManager.cs	(revision 6725)
@@ -133,14 +133,14 @@
     /// <summary>
     /// Updates the plugin cache with missing plugins and 
-    /// then copies the required plugins for the job.
+    /// then copies the required plugins for the task.
     /// </summary>        
-    public void PreparePlugins(Task job, out string configFileName) {
+    public void PreparePlugins(Task task, out string configFileName) {
       lock (locker) {
-        log.LogMessage("Fetching plugins for job " + job.Id);
+        log.LogMessage("Fetching plugins for task " + task.Id);
 
         List<Guid> missingGuids = new List<Guid>();
         List<Plugin> neededPlugins = new List<Plugin>();
         lock (cachedPluginsGuids) {
-          foreach (Guid pluginId in job.PluginsNeededIds) {
+          foreach (Guid pluginId in task.PluginsNeededIds) {
             Plugin plugin = pluginService.GetPlugin(pluginId);
             if (plugin != null) {
@@ -168,9 +168,9 @@
             DoUpdateRun();
           }
-          CopyPluginsForJob(neededPlugins, job.Id, out configFileName);
+          CopyPluginsForJob(neededPlugins, task.Id, out configFileName);
         } else {
           configFileName = "";
         }
-        log.LogMessage(string.Format("Fetched {0} plugins for job {1}", missingGuids.Count, job.Id));
+        log.LogMessage(string.Format("Fetched {0} plugins for task {1}", missingGuids.Count, task.Id));
       }
     }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Manager/TaskManager.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Manager/TaskManager.cs	(revision 6725)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Manager/TaskManager.cs	(revision 6725)
@@ -0,0 +1,335 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Clients.Hive.SlaveCore {
+
+  /// <summary>
+  /// Holds a list of slave tasks and manages access to this list. 
+  /// Forwards events from SlaveTask and forwards commands to SlaveTask. 
+  /// </summary>
+  public class TaskManager {
+    private static ReaderWriterLockSlim slaveTasksLocker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
+    private Dictionary<Guid, SlaveTask> slaveTasks;
+    private ILog log;
+    private PluginManager pluginManager;
+
+    public int TaskCount {
+      get {
+        slaveTasksLocker.EnterReadLock();
+        try {
+          return slaveTasks.Count;
+        }
+        finally { slaveTasksLocker.ExitReadLock(); }
+      }
+    }
+
+    public Guid[] TaskIds {
+      get {
+        slaveTasksLocker.EnterReadLock();
+        try {
+          return slaveTasks.Keys.ToArray();
+        }
+        finally { slaveTasksLocker.ExitReadLock(); }
+      }
+    }
+
+    public TaskManager(PluginManager pluginCache, ILog log) {
+      this.pluginManager = pluginCache;
+      this.log = log;
+      this.slaveTasks = new Dictionary<Guid, SlaveTask>();
+    }
+
+    #region Task Control methods
+    public void StartTaskAsync(Task task, TaskData taskData) {
+      SlaveTask slaveTask = null;
+      slaveTasksLocker.EnterUpgradeableReadLock();
+      try {
+        if (slaveTasks.ContainsKey(task.Id)) {
+          SlaveStatusInfo.IncrementExceptionOccured();
+          throw new TaskAlreadyRunningException(task.Id);
+        } else {
+          slaveTask = new SlaveTask(pluginManager, task.CoresNeeded, log);
+          AddSlaveTask(task, slaveTask);
+          SlaveStatusInfo.IncrementTasksFetched();
+        }
+      }
+      finally { slaveTasksLocker.ExitUpgradeableReadLock(); }
+
+      if (slaveTask != null) {
+        try {
+          slaveTask.StartJobAsync(task, taskData);
+        }
+        catch (Exception) {
+          RemoveSlaveTask(task.Id, slaveTask); // clean up and rethrow
+          slaveTask.DisposeAppDomain();
+          throw;
+        }
+      }
+    }
+
+    public void PauseTaskAsync(Guid taskId) {
+      slaveTasksLocker.EnterUpgradeableReadLock();
+      try {
+        if (!slaveTasks.ContainsKey(taskId)) throw new TaskNotRunningException(taskId);
+        SlaveTask slaveTask = slaveTasks[taskId];
+        slaveTask.PauseTask();
+      }
+      finally { slaveTasksLocker.ExitUpgradeableReadLock(); }
+    }
+
+    public void StopTaskAsync(Guid taskId) {
+      slaveTasksLocker.EnterUpgradeableReadLock();
+      try {
+        if (!slaveTasks.ContainsKey(taskId)) throw new TaskNotRunningException(taskId);
+        SlaveTask slaveTask = slaveTasks[taskId];
+        slaveTask.StopTask();
+      }
+      finally { slaveTasksLocker.ExitUpgradeableReadLock(); }
+    }
+
+    public void AbortTask(Guid taskId) {
+      SlaveTask slaveTask = null;
+      slaveTasksLocker.EnterUpgradeableReadLock();
+      try {
+        if (!slaveTasks.ContainsKey(taskId)) throw new TaskNotRunningException(taskId);
+        slaveTask = slaveTasks[taskId];
+        if (!slaveTask.IsPrepared) throw new AppDomainNotCreatedException();
+        RemoveSlaveTask(taskId, slaveTask);
+      }
+      finally { slaveTasksLocker.ExitUpgradeableReadLock(); }
+      slaveTask.DisposeAppDomain();
+      SlaveStatusInfo.IncrementTasksAborted();
+      OnTaskAborted(slaveTask);
+    }
+
+    public void PauseAllTasksAsync() {
+      slaveTasksLocker.EnterUpgradeableReadLock();
+      try {
+        foreach (var slaveTask in slaveTasks.Values) {
+          slaveTask.PauseTask();
+        }
+      }
+      finally { slaveTasksLocker.ExitUpgradeableReadLock(); }
+    }
+
+    public void StopAllTasksAsync() {
+      slaveTasksLocker.EnterUpgradeableReadLock();
+      try {
+        foreach (var slaveTask in slaveTasks.Values) {
+          slaveTask.StopTask();
+        }
+      }
+      finally { slaveTasksLocker.ExitUpgradeableReadLock(); }
+    }
+
+    public void AbortAllTasks() {
+      slaveTasksLocker.EnterUpgradeableReadLock();
+      try {
+        foreach (var slaveTask in slaveTasks.Values.ToArray()) {
+          AbortTask(slaveTask.TaskId);
+        }
+      }
+      finally { slaveTasksLocker.ExitUpgradeableReadLock(); }
+    }
+    #endregion
+
+    #region Add/Remove SlaveTask
+    private void AddSlaveTask(Task task, SlaveTask slaveTask) {
+      slaveTasksLocker.EnterWriteLock();
+      try {
+        slaveTasks.Add(task.Id, slaveTask);
+        RegisterSlaveTaskEvents(slaveTask);
+      }
+      finally { slaveTasksLocker.ExitWriteLock(); }
+    }
+
+    private void RemoveSlaveTask(Guid taskId, SlaveTask slaveTask) {
+      slaveTasksLocker.EnterWriteLock();
+      try {
+        slaveTasks.Remove(taskId);
+        DeregisterSlaveTaskEvents(slaveTask);
+      }
+      finally { slaveTasksLocker.ExitWriteLock(); }
+    }
+    #endregion
+
+    #region SlaveTask Events
+    private void RegisterSlaveTaskEvents(SlaveTask slaveTask) {
+      slaveTask.TaskStarted += new EventHandler<EventArgs<Guid>>(slaveTask_TaskStarted);
+      slaveTask.TaskPaused += new EventHandler<EventArgs<Guid>>(slaveTask_TaskPaused);
+      slaveTask.TaskStopped += new EventHandler<EventArgs<Guid>>(slaveTask_TaskStopped);
+      slaveTask.TaskFailed += new EventHandler<EventArgs<Guid, Exception>>(slaveTask_TaskFailed);
+      slaveTask.ExceptionOccured += new EventHandler<EventArgs<Guid, Exception>>(slaveTask_ExceptionOccured);
+    }
+
+    private void DeregisterSlaveTaskEvents(SlaveTask slaveTask) {
+      slaveTask.TaskStarted -= new EventHandler<EventArgs<Guid>>(slaveTask_TaskStarted);
+      slaveTask.TaskPaused -= new EventHandler<EventArgs<Guid>>(slaveTask_TaskPaused);
+      slaveTask.TaskStopped -= new EventHandler<EventArgs<Guid>>(slaveTask_TaskStopped);
+      slaveTask.TaskFailed -= new EventHandler<EventArgs<Guid, Exception>>(slaveTask_TaskFailed);
+      slaveTask.ExceptionOccured -= new EventHandler<EventArgs<Guid, Exception>>(slaveTask_ExceptionOccured);
+    }
+
+    private void slaveTask_TaskStarted(object sender, EventArgs<Guid> e) {
+      SlaveTask slaveTask;
+      slaveTasksLocker.EnterUpgradeableReadLock();
+      try {
+        slaveTask = slaveTasks[e.Value];
+      }
+      finally { slaveTasksLocker.ExitUpgradeableReadLock(); }
+
+      SlaveStatusInfo.IncrementTasksStarted();
+      OnTaskStarted(slaveTask);
+    }
+
+    private void slaveTask_TaskPaused(object sender, EventArgs<Guid> e) {
+      SlaveTask slaveTask;
+      slaveTasksLocker.EnterUpgradeableReadLock();
+      try {
+        slaveTask = slaveTasks[e.Value];
+        RemoveSlaveTask(e.Value, slaveTask);
+      }
+      finally { slaveTasksLocker.ExitUpgradeableReadLock(); }
+
+      TaskData taskData = null;
+      try {
+        taskData = slaveTask.GetTaskData();
+        if (taskData == null) throw new SerializationException();
+        SlaveStatusInfo.IncrementTasksFinished();
+        OnTaskPaused(slaveTask, taskData);
+      }
+      catch (Exception ex) {
+        RemoveSlaveTask(e.Value, slaveTask);
+        SlaveStatusInfo.IncrementTasksFailed();
+        OnTaskFailed(slaveTask, taskData, ex);
+      }
+    }
+
+    private void slaveTask_TaskStopped(object sender, EventArgs<Guid> e) {
+      SlaveTask slaveTask;
+      slaveTasksLocker.EnterUpgradeableReadLock();
+      try {
+        slaveTask = slaveTasks[e.Value];
+        RemoveSlaveTask(e.Value, slaveTask);
+      }
+      finally { slaveTasksLocker.ExitUpgradeableReadLock(); }
+
+      TaskData taskData = null;
+      try {
+        taskData = slaveTask.GetTaskData();
+        if (taskData == null) throw new SerializationException();
+        SlaveStatusInfo.IncrementTasksFinished();
+        OnTaskStopped(slaveTask, taskData);
+      }
+      catch (Exception ex) {
+        RemoveSlaveTask(e.Value, slaveTask);
+        SlaveStatusInfo.IncrementTasksFailed();
+        OnTaskFailed(slaveTask, taskData, ex);
+      }
+    }
+
+    private void slaveTask_TaskFailed(object sender, EventArgs<Guid, Exception> e) {
+      SlaveTask slaveTask;
+      slaveTasksLocker.EnterUpgradeableReadLock();
+      try {
+        slaveTask = slaveTasks[e.Value];
+        RemoveSlaveTask(e.Value, slaveTask);
+      }
+      finally { slaveTasksLocker.ExitUpgradeableReadLock(); }
+
+      TaskData taskData = null;
+      try {
+        taskData = slaveTask.GetTaskData();
+        if (taskData == null) throw new SerializationException();
+      }
+      catch { /* taskData will be null */ }
+      SlaveStatusInfo.IncrementTasksFailed();
+      OnTaskFailed(slaveTask, taskData, e.Value2);
+    }
+
+    private void slaveTask_ExceptionOccured(object sender, EventArgs<Guid, Exception> e) {
+      SlaveTask slaveTask;
+      slaveTasksLocker.EnterUpgradeableReadLock();
+      try {
+        slaveTask = slaveTasks[e.Value];
+        RemoveSlaveTask(e.Value, slaveTask);
+      }
+      finally { slaveTasksLocker.ExitUpgradeableReadLock(); }
+
+      SlaveStatusInfo.IncrementExceptionOccured();
+      OnExceptionOccured(slaveTask, e.Value2);
+    }
+    #endregion
+
+    #region EventHandler
+    public event EventHandler<EventArgs<SlaveTask>> TaskStarted;
+    private void OnTaskStarted(SlaveTask slaveTask) {
+      var handler = TaskStarted;
+      if (handler != null) handler(this, new EventArgs<SlaveTask>(slaveTask));
+    }
+
+    public event EventHandler<EventArgs<SlaveTask, TaskData>> TaskStopped;
+    private void OnTaskStopped(SlaveTask slaveTask, TaskData taskData) {
+      var handler = TaskStopped;
+      if (handler != null) handler(this, new EventArgs<SlaveTask, TaskData>(slaveTask, taskData));
+    }
+
+    public event EventHandler<EventArgs<SlaveTask, TaskData>> TaskPaused;
+    private void OnTaskPaused(SlaveTask slaveTask, TaskData taskData) {
+      var handler = TaskPaused;
+      if (handler != null) handler(this, new EventArgs<SlaveTask, TaskData>(slaveTask, taskData));
+    }
+
+    public event EventHandler<EventArgs<Tuple<SlaveTask, TaskData, Exception>>> TaskFailed;
+    private void OnTaskFailed(SlaveTask slaveTask, TaskData taskData, Exception exception) {
+      var handler = TaskFailed;
+      if (handler != null) handler(this, new EventArgs<Tuple<SlaveTask, TaskData, Exception>>(new Tuple<SlaveTask, TaskData, Exception>(slaveTask, taskData, exception)));
+    }
+
+    public event EventHandler<EventArgs<SlaveTask, Exception>> ExceptionOccured;
+    private void OnExceptionOccured(SlaveTask slaveTask, Exception exception) {
+      var handler = ExceptionOccured;
+      if (handler != null) handler(this, new EventArgs<SlaveTask, Exception>(slaveTask, exception));
+    }
+
+    public event EventHandler<EventArgs<SlaveTask>> TaskAborted;
+    private void OnTaskAborted(SlaveTask slaveTask) {
+      var handler = TaskAborted;
+      if (handler != null) handler(this, new EventArgs<SlaveTask>(slaveTask));
+    }
+    #endregion
+
+    public Dictionary<Guid, TimeSpan> GetExecutionTimes() {
+      slaveTasksLocker.EnterReadLock();
+      try {
+        return slaveTasks.ToDictionary(x => x.Key, x => x.Value.ExecutionTime);
+      }
+      finally { slaveTasksLocker.ExitReadLock(); }
+    }
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/SlaveJob.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/SlaveJob.cs	(revision 6723)
+++ 	(revision )
@@ -1,262 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-using System.IO;
-using System.Threading;
-using HeuristicLab.Clients.Hive.SlaveCore.Properties;
-using HeuristicLab.Common;
-using HeuristicLab.Core;
-using HeuristicLab.PluginInfrastructure.Sandboxing;
-
-namespace HeuristicLab.Clients.Hive.SlaveCore {
-
-  /// <summary>
-  ///  Manages a single job and it's appdomain. 
-  /// </summary>
-  public class SlaveJob : MarshalByRefObject {
-    private Executor executor;
-    private AppDomain appDomain;
-    private Semaphore waitForStartBeforeKillSem;
-    private bool executorMonitoringRun;
-    private Thread executorMonitoringThread;
-    private PluginManager pluginManager;
-    private ILog log;
-    public Guid JobId { get; private set; }
-    public bool IsPrepared { get; private set; }
-
-    private int coresNeeded;
-    public int CoresNeeded {
-      get { return coresNeeded; }
-      set { this.coresNeeded = value; }
-    }
-
-    public TimeSpan ExecutionTime {
-      get { return executor != null ? executor.ExecutionTime : TimeSpan.Zero; }
-    }
-
-    public SlaveJob(PluginManager pluginManager, int coresNeeded, ILog log) {
-      this.pluginManager = pluginManager;
-      this.coresNeeded = coresNeeded;
-      this.log = log;
-      waitForStartBeforeKillSem = new Semaphore(0, 1);
-      executorMonitoringRun = true;
-      IsPrepared = false;
-    }
-
-    public void StartJobAsync(Task job, TaskData jobData) {
-      try {
-        this.JobId = job.Id;
-        Prepare(job);
-        StartJobInAppDomain(jobData);
-      }
-      catch (Exception) {
-        // make sure to clean up if something went wrong
-        DisposeAppDomain();
-        throw;
-      }
-    }
-
-    public void PauseJob() {
-      if (!IsPrepared) throw new AppDomainNotCreatedException();
-      if (!executor.IsPausing && !executor.IsStopping) executor.Pause();
-    }
-
-    public void StopJob() {
-      if (!IsPrepared) throw new AppDomainNotCreatedException();
-      if (!executor.IsPausing && !executor.IsStopping) executor.Stop();
-    }
-
-    private void Prepare(Task job) {
-      string pluginDir = Path.Combine(pluginManager.PluginTempBaseDir, job.Id.ToString());
-      string configFileName;
-      pluginManager.PreparePlugins(job, out configFileName);
-      appDomain = CreateAppDomain(job, pluginDir, configFileName);
-      IsPrepared = true;
-    }
-
-    private AppDomain CreateAppDomain(Task job, String pluginDir, string configFileName) {
-      if (job.IsPrivileged) {
-        appDomain = SandboxManager.CreateAndInitPrivilegedSandbox(job.Id.ToString(), pluginDir, Path.Combine(pluginDir, configFileName));
-      } else {
-        appDomain = SandboxManager.CreateAndInitSandbox(job.Id.ToString(), pluginDir, Path.Combine(pluginDir, configFileName));
-      }
-      appDomain.UnhandledException += new UnhandledExceptionEventHandler(AppDomain_UnhandledException);
-
-      log.LogMessage("Creating AppDomain");
-      executor = (Executor)appDomain.CreateInstanceAndUnwrap(typeof(Executor).Assembly.GetName().Name, typeof(Executor).FullName);
-
-      executor.JobId = job.Id;
-      executor.CoresNeeded = job.CoresNeeded;
-      executor.MemoryNeeded = job.MemoryNeeded;
-      return appDomain;
-    }
-
-    private void StartJobInAppDomain(TaskData jobData) {
-      executor.Start(jobData.Data);
-      waitForStartBeforeKillSem.Release();
-      StartExecutorMonitoringThread();
-    }
-
-    public void DisposeAppDomain() {
-      log.LogMessage(string.Format("Shutting down Appdomain for Task {0}", JobId));
-      StopExecutorMonitoringThread();
-
-      if (executor != null) {
-        executor.Dispose();
-      }
-
-      if (appDomain != null) {
-        appDomain.UnhandledException -= new UnhandledExceptionEventHandler(AppDomain_UnhandledException);
-        int repeat = Settings.Default.PluginDeletionRetries;
-        while (repeat > 0) {
-          try {
-            waitForStartBeforeKillSem.WaitOne();
-            AppDomain.Unload(appDomain);
-            waitForStartBeforeKillSem.Dispose();
-            repeat = 0;
-          }
-          catch (CannotUnloadAppDomainException) {
-            log.LogMessage("Could not unload AppDomain, will try again in 1 sec.");
-            Thread.Sleep(Settings.Default.PluginDeletionTimeout);
-            repeat--;
-            if (repeat == 0) {
-              throw; // rethrow and let app crash
-            }
-          }
-        }
-      }
-      pluginManager.DeletePluginsForJob(JobId);
-      GC.Collect();
-    }
-
-    private void AppDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
-      DisposeAppDomain();
-      OnExceptionOccured(new Exception("Unhandled exception: " + e.ExceptionObject.ToString()));
-    }
-
-    public TaskData GetJobData() {
-      return executor.GetJobData();
-    }
-
-    #region ExecutorMonitorThread
-    private void StartExecutorMonitoringThread() {
-      executorMonitoringThread = new Thread(MonitorExecutor);
-      executorMonitoringThread.Start();
-    }
-
-    private void StopExecutorMonitoringThread() {
-      if (executorMonitoringThread != null) {
-        if (executorMonitoringRun) {
-          executorMonitoringRun = false;
-          executor.ExecutorCommandQueue.AddMessage(ExecutorMessageType.StopExecutorMonitoringThread);
-        }
-      }
-    }
-
-    /// <summary>
-    /// Because the executor is in an appdomain and is not able to call back 
-    /// (because of security -> lease time for marshall-by-ref object is 5 min),
-    /// we have to poll the executor for events we have to react to (e.g. job finished...)    
-    /// </summary>
-    private void MonitorExecutor() {
-      while (executorMonitoringRun) {
-        //this blocks through the appdomain border, that's why the lease gets renewed
-        ExecutorMessage message = executor.ExecutorCommandQueue.GetMessage();
-
-        switch (message.MessageType) {
-          case ExecutorMessageType.JobStarted:
-            OnJobStarted();
-            break;
-
-          case ExecutorMessageType.JobPaused:
-            executorMonitoringRun = false;
-            OnJobPaused();
-            DisposeAppDomain();
-            break;
-
-          case ExecutorMessageType.JobStopped:
-            executorMonitoringRun = false;
-            OnJobStopped();
-            DisposeAppDomain();
-            break;
-
-          case ExecutorMessageType.JobFailed:
-            executorMonitoringRun = false;
-            OnJobFailed(new JobFailedException(executor.CurrentExceptionStr));
-            DisposeAppDomain();
-            break;
-
-          case ExecutorMessageType.StopExecutorMonitoringThread:
-            executorMonitoringRun = false;
-            break;
-
-          case ExecutorMessageType.ExceptionOccured:
-            executorMonitoringRun = false;
-            DisposeAppDomain();
-            if (executor.CurrentException != null) {
-              OnExceptionOccured(executor.CurrentException);
-            } else {
-              OnExceptionOccured(new Exception(string.Format("Unknow exception occured in Executor for job {0}", JobId)));
-            }
-            break;
-        }
-      }
-    }
-    #endregion
-
-    public event EventHandler<EventArgs<Guid>> JobStarted;
-    private void OnJobStarted() {
-      var handler = JobStarted;
-      if (handler != null) handler(this, new EventArgs<Guid>(this.JobId));
-    }
-
-    public event EventHandler<EventArgs<Guid>> JobStopped;
-    private void OnJobStopped() {
-      var handler = JobStopped;
-      if (handler != null) handler(this, new EventArgs<Guid>(this.JobId));
-    }
-
-    public event EventHandler<EventArgs<Guid>> JobPaused;
-    private void OnJobPaused() {
-      var handler = JobPaused;
-      if (handler != null) handler(this, new EventArgs<Guid>(this.JobId));
-    }
-
-    public event EventHandler<EventArgs<Guid>> JobAborted;
-    private void OnJobAborted() {
-      var handler = JobAborted;
-      if (handler != null) handler(this, new EventArgs<Guid>(this.JobId));
-    }
-
-    public event EventHandler<EventArgs<Guid, Exception>> JobFailed;
-    private void OnJobFailed(Exception exception) {
-      var handler = JobFailed;
-      if (handler != null) handler(this, new EventArgs<Guid, Exception>(this.JobId, exception));
-    }
-
-    public event EventHandler<EventArgs<Guid, Exception>> ExceptionOccured;
-    private void OnExceptionOccured(Exception exception) {
-      var handler = ExceptionOccured;
-      if (handler != null) handler(this, new EventArgs<Guid, Exception>(this.JobId, exception));
-    }
-  }
-}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/SlaveStatusInfo.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/SlaveStatusInfo.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/SlaveStatusInfo.cs	(revision 6725)
@@ -26,10 +26,10 @@
   public class SlaveStatusInfo {
     private static object coreLock = new object();
-    private static int jobsFetched;  // number of fetched jobs
-    private static int jobsStarted;  // number of started jobs
-    private static int jobsFinished; // everything went fine
-    private static int jobsAborted;  // server sent abort
-    private static int jobsFailed;   // jobs that failed in the sandbox
-    private static int exceptionsOccured; // number jobs failed caused by the business logic, not a faulted job
+    private static int tasksFetched;  // number of fetched jobs
+    private static int tasksStarted;  // number of started jobs
+    private static int tasksFinished; // everything went fine
+    private static int tasksAborted;  // server sent abort
+    private static int tasksFailed;   // tasks that failed in the sandbox
+    private static int exceptionsOccured; // number jobs failed caused by the business logic, not a faulted task
     private static int usedCores;    // number of cores currently used
 
@@ -40,22 +40,22 @@
     }
 
-    public static int JobsStarted {
-      get { return jobsStarted; }
+    public static int TasksStarted {
+      get { return tasksStarted; }
     }
 
-    public static int JobsFinished {
-      get { return jobsFinished; }
+    public static int TasksFinished {
+      get { return tasksFinished; }
     }
 
-    public static int JobsAborted {
-      get { return jobsAborted; }
+    public static int TasksAborted {
+      get { return tasksAborted; }
     }
 
-    public static int JobsFetched {
-      get { return jobsFetched; }
+    public static int TasksFetched {
+      get { return tasksFetched; }
     }
 
-    public static int JobsFailed {
-      get { return jobsFailed; }
+    public static int TasksFailed {
+      get { return tasksFailed; }
     }
 
@@ -64,22 +64,22 @@
     }
 
-    public static void IncrementJobsStarted() {
-      Interlocked.Increment(ref jobsStarted);
+    public static void IncrementTasksStarted() {
+      Interlocked.Increment(ref tasksStarted);
     }
 
-    public static void IncrementJobsFinished() {
-      Interlocked.Increment(ref jobsFinished);
+    public static void IncrementTasksFinished() {
+      Interlocked.Increment(ref tasksFinished);
     }
 
-    public static void IncrementJobsFailed() {
-      Interlocked.Increment(ref jobsFailed);
+    public static void IncrementTasksFailed() {
+      Interlocked.Increment(ref tasksFailed);
     }
 
-    public static void IncrementJobsAborted() {
-      Interlocked.Increment(ref jobsAborted);
+    public static void IncrementTasksAborted() {
+      Interlocked.Increment(ref tasksAborted);
     }
 
-    public static void IncrementJobsFetched() {
-      Interlocked.Increment(ref jobsFetched);
+    public static void IncrementTasksFetched() {
+      Interlocked.Increment(ref tasksFetched);
     }
 
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/SlaveTask.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/SlaveTask.cs	(revision 6725)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/SlaveTask.cs	(revision 6725)
@@ -0,0 +1,262 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.IO;
+using System.Threading;
+using HeuristicLab.Clients.Hive.SlaveCore.Properties;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.PluginInfrastructure.Sandboxing;
+
+namespace HeuristicLab.Clients.Hive.SlaveCore {
+
+  /// <summary>
+  ///  Manages a single task and it's appdomain. 
+  /// </summary>
+  public class SlaveTask : MarshalByRefObject {
+    private Executor executor;
+    private AppDomain appDomain;
+    private Semaphore waitForStartBeforeKillSem;
+    private bool executorMonitoringRun;
+    private Thread executorMonitoringThread;
+    private PluginManager pluginManager;
+    private ILog log;
+    public Guid TaskId { get; private set; }
+    public bool IsPrepared { get; private set; }
+
+    private int coresNeeded;
+    public int CoresNeeded {
+      get { return coresNeeded; }
+      set { this.coresNeeded = value; }
+    }
+
+    public TimeSpan ExecutionTime {
+      get { return executor != null ? executor.ExecutionTime : TimeSpan.Zero; }
+    }
+
+    public SlaveTask(PluginManager pluginManager, int coresNeeded, ILog log) {
+      this.pluginManager = pluginManager;
+      this.coresNeeded = coresNeeded;
+      this.log = log;
+      waitForStartBeforeKillSem = new Semaphore(0, 1);
+      executorMonitoringRun = true;
+      IsPrepared = false;
+    }
+
+    public void StartJobAsync(Task task, TaskData taskData) {
+      try {
+        this.TaskId = task.Id;
+        Prepare(task);
+        StartTaskInAppDomain(taskData);
+      }
+      catch (Exception) {
+        // make sure to clean up if something went wrong
+        DisposeAppDomain();
+        throw;
+      }
+    }
+
+    public void PauseTask() {
+      if (!IsPrepared) throw new AppDomainNotCreatedException();
+      if (!executor.IsPausing && !executor.IsStopping) executor.Pause();
+    }
+
+    public void StopTask() {
+      if (!IsPrepared) throw new AppDomainNotCreatedException();
+      if (!executor.IsPausing && !executor.IsStopping) executor.Stop();
+    }
+
+    private void Prepare(Task task) {
+      string pluginDir = Path.Combine(pluginManager.PluginTempBaseDir, task.Id.ToString());
+      string configFileName;
+      pluginManager.PreparePlugins(task, out configFileName);
+      appDomain = CreateAppDomain(task, pluginDir, configFileName);
+      IsPrepared = true;
+    }
+
+    private AppDomain CreateAppDomain(Task task, String pluginDir, string configFileName) {
+      if (task.IsPrivileged) {
+        appDomain = SandboxManager.CreateAndInitPrivilegedSandbox(task.Id.ToString(), pluginDir, Path.Combine(pluginDir, configFileName));
+      } else {
+        appDomain = SandboxManager.CreateAndInitSandbox(task.Id.ToString(), pluginDir, Path.Combine(pluginDir, configFileName));
+      }
+      appDomain.UnhandledException += new UnhandledExceptionEventHandler(AppDomain_UnhandledException);
+
+      log.LogMessage("Creating AppDomain");
+      executor = (Executor)appDomain.CreateInstanceAndUnwrap(typeof(Executor).Assembly.GetName().Name, typeof(Executor).FullName);
+
+      executor.TaskId = task.Id;
+      executor.CoresNeeded = task.CoresNeeded;
+      executor.MemoryNeeded = task.MemoryNeeded;
+      return appDomain;
+    }
+
+    private void StartTaskInAppDomain(TaskData taskData) {
+      executor.Start(taskData.Data);
+      waitForStartBeforeKillSem.Release();
+      StartExecutorMonitoringThread();
+    }
+
+    public void DisposeAppDomain() {
+      log.LogMessage(string.Format("Shutting down Appdomain for Task {0}", TaskId));
+      StopExecutorMonitoringThread();
+
+      if (executor != null) {
+        executor.Dispose();
+      }
+
+      if (appDomain != null) {
+        appDomain.UnhandledException -= new UnhandledExceptionEventHandler(AppDomain_UnhandledException);
+        int repeat = Settings.Default.PluginDeletionRetries;
+        while (repeat > 0) {
+          try {
+            waitForStartBeforeKillSem.WaitOne();
+            AppDomain.Unload(appDomain);
+            waitForStartBeforeKillSem.Dispose();
+            repeat = 0;
+          }
+          catch (CannotUnloadAppDomainException) {
+            log.LogMessage("Could not unload AppDomain, will try again in 1 sec.");
+            Thread.Sleep(Settings.Default.PluginDeletionTimeout);
+            repeat--;
+            if (repeat == 0) {
+              throw; // rethrow and let app crash
+            }
+          }
+        }
+      }
+      pluginManager.DeletePluginsForJob(TaskId);
+      GC.Collect();
+    }
+
+    private void AppDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
+      DisposeAppDomain();
+      OnExceptionOccured(new Exception("Unhandled exception: " + e.ExceptionObject.ToString()));
+    }
+
+    public TaskData GetTaskData() {
+      return executor.GetTaskData();
+    }
+
+    #region ExecutorMonitorThread
+    private void StartExecutorMonitoringThread() {
+      executorMonitoringThread = new Thread(MonitorExecutor);
+      executorMonitoringThread.Start();
+    }
+
+    private void StopExecutorMonitoringThread() {
+      if (executorMonitoringThread != null) {
+        if (executorMonitoringRun) {
+          executorMonitoringRun = false;
+          executor.ExecutorCommandQueue.AddMessage(ExecutorMessageType.StopExecutorMonitoringThread);
+        }
+      }
+    }
+
+    /// <summary>
+    /// Because the executor is in an appdomain and is not able to call back 
+    /// (because of security -> lease time for marshall-by-ref object is 5 min),
+    /// we have to poll the executor for events we have to react to (e.g. task finished...)    
+    /// </summary>
+    private void MonitorExecutor() {
+      while (executorMonitoringRun) {
+        //this blocks through the appdomain border, that's why the lease gets renewed
+        ExecutorMessage message = executor.ExecutorCommandQueue.GetMessage();
+
+        switch (message.MessageType) {
+          case ExecutorMessageType.TaskStarted:
+            OnTaskStarted();
+            break;
+
+          case ExecutorMessageType.TaskPaused:
+            executorMonitoringRun = false;
+            OnTaskPaused();
+            DisposeAppDomain();
+            break;
+
+          case ExecutorMessageType.TaskStopped:
+            executorMonitoringRun = false;
+            OnTaskStopped();
+            DisposeAppDomain();
+            break;
+
+          case ExecutorMessageType.TaskFailed:
+            executorMonitoringRun = false;
+            OnTaskFailed(new TaskFailedException(executor.CurrentExceptionStr));
+            DisposeAppDomain();
+            break;
+
+          case ExecutorMessageType.StopExecutorMonitoringThread:
+            executorMonitoringRun = false;
+            break;
+
+          case ExecutorMessageType.ExceptionOccured:
+            executorMonitoringRun = false;
+            DisposeAppDomain();
+            if (executor.CurrentException != null) {
+              OnExceptionOccured(executor.CurrentException);
+            } else {
+              OnExceptionOccured(new Exception(string.Format("Unknow exception occured in Executor for task {0}", TaskId)));
+            }
+            break;
+        }
+      }
+    }
+    #endregion
+
+    public event EventHandler<EventArgs<Guid>> TaskStarted;
+    private void OnTaskStarted() {
+      var handler = TaskStarted;
+      if (handler != null) handler(this, new EventArgs<Guid>(this.TaskId));
+    }
+
+    public event EventHandler<EventArgs<Guid>> TaskStopped;
+    private void OnTaskStopped() {
+      var handler = TaskStopped;
+      if (handler != null) handler(this, new EventArgs<Guid>(this.TaskId));
+    }
+
+    public event EventHandler<EventArgs<Guid>> TaskPaused;
+    private void OnTaskPaused() {
+      var handler = TaskPaused;
+      if (handler != null) handler(this, new EventArgs<Guid>(this.TaskId));
+    }
+
+    public event EventHandler<EventArgs<Guid>> TaskAborted;
+    private void OnTaskAborted() {
+      var handler = TaskAborted;
+      if (handler != null) handler(this, new EventArgs<Guid>(this.TaskId));
+    }
+
+    public event EventHandler<EventArgs<Guid, Exception>> TaskFailed;
+    private void OnTaskFailed(Exception exception) {
+      var handler = TaskFailed;
+      if (handler != null) handler(this, new EventArgs<Guid, Exception>(this.TaskId, exception));
+    }
+
+    public event EventHandler<EventArgs<Guid, Exception>> ExceptionOccured;
+    private void OnExceptionOccured(Exception exception) {
+      var handler = ExceptionOccured;
+      if (handler != null) handler(this, new EventArgs<Guid, Exception>(this.TaskId, exception));
+    }
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/StatusCommons.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/StatusCommons.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/StatusCommons.cs	(revision 6725)
@@ -53,5 +53,5 @@
     public int ExceptionsOccured { get; set; }
     [DataMember]
-    public List<JobStatus> Jobs { get; set; }
+    public List<TaskStatus> Jobs { get; set; }
     [DataMember]
     public bool Asleep { get; set; }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/TaskStatus.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/TaskStatus.cs	(revision 6725)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/TaskStatus.cs	(revision 6725)
@@ -0,0 +1,39 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Runtime.Serialization;
+
+namespace HeuristicLab.Clients.Hive.SlaveCore {
+  [DataContract]
+  public class TaskStatus {
+    /// <summary>
+    /// Id of the Task
+    /// </summary>
+    [DataMember]
+    public Guid TaskId { get; set; }
+    /// <summary>
+    /// Current progress
+    /// </summary>
+    [DataMember]
+    public TimeSpan ExecutionTime { get; set; }
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/WcfService.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/WcfService.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/WcfService.cs	(revision 6725)
@@ -70,5 +70,5 @@
 
     /// <summary>
-    /// Uploads the jobData and sets a new jobState (while correctly setting Transferring state)
+    /// Uploads the taskData and sets a new jobState (while correctly setting Transferring state)
     /// </summary>
     public void UpdateJobData(Task job, TaskData jobData, Guid slaveId, TaskState state, string exception = "") {
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Tests/ExperimentManagerTests.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Tests/ExperimentManagerTests.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Tests/ExperimentManagerTests.cs	(revision 6725)
@@ -43,7 +43,7 @@
     [TestMethod]
     public void TestExperimentUpload() {
-      var rhc = new RefreshableHiveExperiment();
+      var rhc = new RefreshableJob();
       var optimizer = CreateOptimizer();
-      rhc.HiveJobs.Add(new OptimizerHiveJob(optimizer));
+      rhc.HiveJobs.Add(new OptimizerHiveTask(optimizer));
       
       HiveClient.StartExperiment((Exception ex) => TestContext.WriteLine(ex.ToString()), rhc, new CancellationToken());
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Views/3.3/HiveJobs/HiveJobListView.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Views/3.3/HiveJobs/HiveJobListView.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Views/3.3/HiveJobs/HiveJobListView.cs	(revision 6725)
@@ -27,6 +27,6 @@
 namespace HeuristicLab.Clients.Hive.Views {
   [View("JobItemList View")]
-  [Content(typeof(IItemList<HiveJob>), false)]
-  public partial class HiveJobListView : ItemListView<HiveJob> {
+  [Content(typeof(IItemList<HiveTask>), false)]
+  public partial class HiveJobListView : ItemListView<HiveTask> {
 
     public HiveJobListView() {
@@ -35,5 +35,5 @@
     }
 
-    protected override HiveJob CreateItem() {
+    protected override HiveTask CreateItem() {
       return null;
     }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Views/3.3/HiveJobs/HiveJobView.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Views/3.3/HiveJobs/HiveJobView.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Views/3.3/HiveJobs/HiveJobView.cs	(revision 6725)
@@ -26,10 +26,10 @@
 
 namespace HeuristicLab.Clients.Hive.Views {
-  [View("HiveJob View")]
-  [Content(typeof(HiveJob), true)]
-  [Content(typeof(HiveJob<>), false)]
+  [View("HiveTask View")]
+  [Content(typeof(HiveTask), true)]
+  [Content(typeof(HiveTask<>), false)]
   public partial class HiveJobView : ItemView {
-    public new HiveJob Content {
-      get { return (HiveJob)base.Content; }
+    public new HiveTask Content {
+      get { return (HiveTask)base.Content; }
       set {
         if (base.Content != value) {
@@ -61,6 +61,6 @@
     protected override void OnContentChanged() {
       base.OnContentChanged();
-      if (Content != null && Content.Job != null) {
-        computeInParallelCheckBox.Checked = Content.ItemJob.ComputeInParallel;
+      if (Content != null && Content.Task != null) {
+        computeInParallelCheckBox.Checked = Content.ItemTask.ComputeInParallel;
       } else {
         computeInParallelCheckBox.Checked = false;
@@ -72,14 +72,14 @@
 
     protected virtual void RegisterJobEvents() {
-      if (Content != null && Content.Job != null) {
-        Content.ItemJob.ComputeInParallelChanged += new EventHandler(OptimizerJob_ComputeInParallelChanged);
-        Content.ItemJob.ItemChanged += new EventHandler(Job_ItemChanged);
+      if (Content != null && Content.Task != null) {
+        Content.ItemTask.ComputeInParallelChanged += new EventHandler(OptimizerJob_ComputeInParallelChanged);
+        Content.ItemTask.ItemChanged += new EventHandler(Job_ItemChanged);
       }
     }
 
     protected virtual void DeregisterJobEvents() {
-      if (Content != null && Content.Job != null) {
-        Content.ItemJob.ComputeInParallelChanged -= new EventHandler(OptimizerJob_ComputeInParallelChanged);
-        Content.ItemJob.ItemChanged -= new EventHandler(Job_ItemChanged);
+      if (Content != null && Content.Task != null) {
+        Content.ItemTask.ComputeInParallelChanged -= new EventHandler(OptimizerJob_ComputeInParallelChanged);
+        Content.ItemTask.ItemChanged -= new EventHandler(Job_ItemChanged);
       }
     }
@@ -90,10 +90,10 @@
         Invoke(new EventHandler(Content_JobChanged), sender, e);
       } else {
-        if (Content != null && Content.Job != null) {
-          this.jobIdTextBox.Text = Content.Job.Id.ToString();
-          this.dateCreatedTextBox.Text = Content.Job.DateCreated.HasValue ? Content.Job.DateCreated.ToString() : string.Empty;
-          this.priorityTextBox.Text = Content.Job.Priority.ToString();
-          this.coresNeededTextBox.Text = Content.Job.CoresNeeded.ToString();
-          this.memoryNeededTextBox.Text = Content.Job.MemoryNeeded.ToString();
+        if (Content != null && Content.Task != null) {
+          this.jobIdTextBox.Text = Content.Task.Id.ToString();
+          this.dateCreatedTextBox.Text = Content.Task.DateCreated.HasValue ? Content.Task.DateCreated.ToString() : string.Empty;
+          this.priorityTextBox.Text = Content.Task.Priority.ToString();
+          this.coresNeededTextBox.Text = Content.Task.CoresNeeded.ToString();
+          this.memoryNeededTextBox.Text = Content.Task.MemoryNeeded.ToString();
         } else {
           this.jobIdTextBox.Text = string.Empty;
@@ -112,6 +112,6 @@
 
     protected virtual void Job_ItemChanged(object sender, EventArgs e) {
-      if (Content != null && Content.Job != null && Content.ItemJob.Item != null) {
-        optimizerItemView.Content = Content.ItemJob.Item;
+      if (Content != null && Content.Task != null && Content.ItemTask.Item != null) {
+        optimizerItemView.Content = Content.ItemTask.Item;
       } else {
         optimizerItemView.Content = null;
@@ -123,11 +123,11 @@
         Invoke(new EventHandler(Content_TaskStateChanged), sender, e);
       } else {
-        if (Content != null && Content.Job != null) {
-          this.stateTextBox.Text = Content.Job.State.ToString();
-          this.commandTextBox.Text = Content.Job.Command.ToString();
-          this.executionTimeTextBox.Text = Content.Job.ExecutionTime.ToString();
-          this.dateFinishedTextBox.Text = Content.Job.DateFinished.ToString();
-          this.exceptionTextBox.Text = Content.Job.CurrentStateLog != null ? Content.Job.CurrentStateLog.Exception : string.Empty;
-          this.lastUpdatedTextBox.Text = Content.Job.LastJobDataUpdate.ToString();
+        if (Content != null && Content.Task != null) {
+          this.stateTextBox.Text = Content.Task.State.ToString();
+          this.commandTextBox.Text = Content.Task.Command.ToString();
+          this.executionTimeTextBox.Text = Content.Task.ExecutionTime.ToString();
+          this.dateFinishedTextBox.Text = Content.Task.DateFinished.ToString();
+          this.exceptionTextBox.Text = Content.Task.CurrentStateLog != null ? Content.Task.CurrentStateLog.Exception : string.Empty;
+          this.lastUpdatedTextBox.Text = Content.Task.LastJobDataUpdate.ToString();
         } else {
           this.stateTextBox.Text = string.Empty;
@@ -148,5 +148,5 @@
         Invoke(new EventHandler(OptimizerJob_ComputeInParallelChanged), sender, e);
       } else {
-        computeInParallelCheckBox.Checked = Content.ItemJob.ComputeInParallel;
+        computeInParallelCheckBox.Checked = Content.ItemTask.ComputeInParallel;
       }
     }
@@ -154,5 +154,5 @@
     protected virtual void Content_StateLogChanged(object sender, EventArgs e) {
       if (Content != null) {
-        if (Content.ItemJob.ComputeInParallel) {
+        if (Content.ItemTask.ComputeInParallel) {
           this.stateLogViewHost.Content = Content.ChildStateLogList;
         } else {
@@ -167,6 +167,6 @@
     #region Child Control Events
     protected virtual void computeInParallelCheckBox_CheckedChanged(object sender, EventArgs e) {
-      if (Content != null && Content.ItemJob != null) {
-        this.Content.ItemJob.ComputeInParallel = this.computeInParallelCheckBox.Checked;
+      if (Content != null && Content.ItemTask != null) {
+        this.Content.ItemTask.ComputeInParallel = this.computeInParallelCheckBox.Checked;
       }
     }
@@ -180,5 +180,5 @@
 
     protected virtual void modifyItemButton_Click(object sender, EventArgs e) {
-      MainFormManager.MainForm.ShowContent(Content.ItemJob.Item);
+      MainFormManager.MainForm.ShowContent(Content.ItemTask.Item);
     }
     #endregion
@@ -199,7 +199,7 @@
       this.coresNeededTextBox.ReadOnly = this.ReadOnly;
       this.memoryNeededTextBox.ReadOnly = this.ReadOnly;
-      this.computeInParallelCheckBox.Enabled = !this.ReadOnly && this.Content != null && this.Content.ItemJob != null && this.Content.ItemJob.IsParallelizable;
-
-      this.modifyItemButton.Enabled = (Content != null && Content.ItemJob.Item != null && (Content.Job.State == TaskState.Paused || Content.Job.State == TaskState.Offline || Content.Job.State == TaskState.Finished || Content.Job.State == TaskState.Failed || Content.Job.State == TaskState.Aborted));
+      this.computeInParallelCheckBox.Enabled = !this.ReadOnly && this.Content != null && this.Content.ItemTask != null && this.Content.ItemTask.IsParallelizable;
+
+      this.modifyItemButton.Enabled = (Content != null && Content.ItemTask.Item != null && (Content.Task.State == TaskState.Paused || Content.Task.State == TaskState.Offline || Content.Task.State == TaskState.Finished || Content.Task.State == TaskState.Failed || Content.Task.State == TaskState.Aborted));
 
       optimizerItemView.ReadOnly = true;
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Views/3.3/HiveJobs/OptimizerHiveJobView.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Views/3.3/HiveJobs/OptimizerHiveJobView.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Views/3.3/HiveJobs/OptimizerHiveJobView.cs	(revision 6725)
@@ -25,9 +25,9 @@
 
 namespace HeuristicLab.Clients.Hive.Views {
-  [View("OptimizerHiveJob View")]
-  [Content(typeof(OptimizerHiveJob), true)]
+  [View("OptimizerHiveTask View")]
+  [Content(typeof(OptimizerHiveTask), true)]
   public partial class OptimizerHiveJobView : HiveJobView {
-    public new OptimizerHiveJob Content {
-      get { return (OptimizerHiveJob)base.Content; }
+    public new OptimizerHiveTask Content {
+      get { return (OptimizerHiveTask)base.Content; }
       set {
         if (base.Content != value) {
@@ -42,6 +42,6 @@
 
     protected override void Job_ItemChanged(object sender, EventArgs e) {
-      if (Content != null && Content.Job != null && Content.ItemJob.Item != null) {
-        runCollectionViewHost.Content = Content.ItemJob.Item.Runs;
+      if (Content != null && Content.Task != null && Content.ItemTask.Item != null) {
+        runCollectionViewHost.Content = Content.ItemTask.Item.Runs;
       } else {
         runCollectionViewHost.Content = null;
@@ -82,7 +82,7 @@
       base.SetEnabledStateOfControls();
 
-      this.restartButton.Enabled = Content != null && Content.IsControllable && !Content.Job.Command.HasValue && (Content.Job.State == TaskState.Paused || Content.Job.State == TaskState.Failed || Content.Job.State == TaskState.Aborted);
-      this.pauseButton.Enabled = Content != null && Content.IsControllable && !Content.Job.Command.HasValue && Content.Job.State == TaskState.Calculating;
-      this.stopButton.Enabled = Content != null && Content.IsControllable && !Content.Job.Command.HasValue && (Content.Job.State == TaskState.Calculating || Content.Job.State == TaskState.Waiting || Content.Job.State == TaskState.Paused);
+      this.restartButton.Enabled = Content != null && Content.IsControllable && !Content.Task.Command.HasValue && (Content.Task.State == TaskState.Paused || Content.Task.State == TaskState.Failed || Content.Task.State == TaskState.Aborted);
+      this.pauseButton.Enabled = Content != null && Content.IsControllable && !Content.Task.Command.HasValue && Content.Task.State == TaskState.Calculating;
+      this.stopButton.Enabled = Content != null && Content.IsControllable && !Content.Task.Command.HasValue && (Content.Task.State == TaskState.Calculating || Content.Task.State == TaskState.Waiting || Content.Task.State == TaskState.Paused);
     }
   }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Views/3.3/TreeView/DeleteJobTreeNodeAction.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Views/3.3/TreeView/DeleteJobTreeNodeAction.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Views/3.3/TreeView/DeleteJobTreeNodeAction.cs	(revision 6725)
@@ -5,8 +5,8 @@
 using HeuristicLab.Optimization;
 namespace HeuristicLab.Clients.Hive.Views.ExperimentManager.TreeView {
-  public class DeleteJobTreeNodeAction : IItemTreeNodeAction<HiveJob> {
-    private ItemCollection<HiveJob> hiveJobs;
+  public class DeleteJobTreeNodeAction : IItemTreeNodeAction<HiveTask> {
+    private ItemCollection<HiveTask> hiveJobs;
     
-    public DeleteJobTreeNodeAction(ItemCollection<HiveJob> hiveJobs) {
+    public DeleteJobTreeNodeAction(ItemCollection<HiveTask> hiveJobs) {
       this.hiveJobs = hiveJobs;
     }
@@ -20,11 +20,11 @@
     }
 
-    public void Execute(HiveJob item, HiveJob parentItem) {
+    public void Execute(HiveTask item, HiveTask parentItem) {
       if (parentItem == null) {
         hiveJobs.Remove(item);
       } else {
-        var experiment = parentItem.ItemJob.Item as Experiment;
+        var experiment = parentItem.ItemTask.Item as Experiment;
         if (experiment != null) {
-          experiment.Optimizers.Remove(((OptimizerJob)item.ItemJob).Item);
+          experiment.Optimizers.Remove(((OptimizerTask)item.ItemTask).Item);
         }
       }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Views/3.3/TreeView/HiveJobItemTreeView.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Views/3.3/TreeView/HiveJobItemTreeView.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Views/3.3/TreeView/HiveJobItemTreeView.cs	(revision 6725)
@@ -30,9 +30,9 @@
 
 namespace HeuristicLab.Clients.Hive.Views.ExperimentManager {
-  [View("HiveJob ItemTreeView")]
-  [Content(typeof(ItemCollection<HiveJob>), IsDefaultView = false)]
-  public partial class HiveJobItemTreeView : ItemTreeView<HiveJob> {
-    public new ItemCollection<HiveJob> Content {
-      get { return (ItemCollection<HiveJob>)base.Content; }
+  [View("HiveTask ItemTreeView")]
+  [Content(typeof(ItemCollection<HiveTask>), IsDefaultView = false)]
+  public partial class HiveJobItemTreeView : ItemTreeView<HiveTask> {
+    public new ItemCollection<HiveTask> Content {
+      get { return (ItemCollection<HiveTask>)base.Content; }
       set { base.Content = value; }
     }
@@ -76,7 +76,7 @@
       if (optimizer != null) {
         if (treeView.SelectedNode == null) {
-          Content.Add(new OptimizerHiveJob(optimizer));
+          Content.Add(new OptimizerHiveTask(optimizer));
         } else {
-          var experiment = ((HiveJob)treeView.SelectedNode.Tag).ItemJob.Item as Experiment;
+          var experiment = ((HiveTask)treeView.SelectedNode.Tag).ItemTask.Item as Experiment;
           if (experiment != null) {
             experiment.Optimizers.Add(optimizer);
@@ -88,12 +88,12 @@
     protected override void removeButton_Click(object sender, EventArgs e) {
       if (treeView.SelectedNode != null) {
-        var selectedItem = (HiveJob)treeView.SelectedNode.Tag;
+        var selectedItem = (HiveTask)treeView.SelectedNode.Tag;
         var parentItem = GetParentItem(selectedItem);
         if (parentItem == null) {
-          Content.Remove((HiveJob)treeView.SelectedNode.Tag);
+          Content.Remove((HiveTask)treeView.SelectedNode.Tag);
         } else {
-          var experiment = parentItem.ItemJob.Item as Experiment;
+          var experiment = parentItem.ItemTask.Item as Experiment;
           if (experiment != null) {
-            experiment.Optimizers.Remove(((OptimizerJob)selectedItem.ItemJob).Item);
+            experiment.Optimizers.Remove(((OptimizerTask)selectedItem.ItemTask).Item);
           }
         }
@@ -102,5 +102,5 @@
     #endregion
 
-    protected override ICollection<IItemTreeNodeAction<HiveJob>> GetTreeNodeItemActions(HiveJob selectedItem) {
+    protected override ICollection<IItemTreeNodeAction<HiveTask>> GetTreeNodeItemActions(HiveTask selectedItem) {
       return base.GetTreeNodeItemActions(selectedItem);
     }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Views/3.3/TreeView/NewExperimentTreeNodeAction.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Views/3.3/TreeView/NewExperimentTreeNodeAction.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Views/3.3/TreeView/NewExperimentTreeNodeAction.cs	(revision 6725)
@@ -25,8 +25,8 @@
 
 namespace HeuristicLab.Clients.Hive {
-  public class NewExperimentTreeNodeAction : IItemTreeNodeAction<HiveJob> {
-    private ItemCollection<HiveJob> hiveJobs;
+  public class NewExperimentTreeNodeAction : IItemTreeNodeAction<HiveTask> {
+    private ItemCollection<HiveTask> hiveJobs;
 
-    public NewExperimentTreeNodeAction(ItemCollection<HiveJob> hiveJobs) {
+    public NewExperimentTreeNodeAction(ItemCollection<HiveTask> hiveJobs) {
       this.hiveJobs = hiveJobs;
     }
@@ -40,10 +40,10 @@
     }
 
-    public void Execute(HiveJob item, HiveJob parentItem) {
+    public void Execute(HiveTask item, HiveTask parentItem) {
       if (item != null) {
-        var experiment = item.ItemJob.Item as Experiment;
+        var experiment = item.ItemTask.Item as Experiment;
         experiment.Optimizers.Add(new Experiment());
       } else {
-        hiveJobs.Add(new OptimizerHiveJob(new Experiment()));
+        hiveJobs.Add(new OptimizerHiveTask(new Experiment()));
       }
     }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/ConcurrentJobDownloader.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/ConcurrentJobDownloader.cs	(revision 6723)
+++ 	(revision )
@@ -1,99 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-using System.Threading;
-using System.Threading.Tasks;
-using HeuristicLab.Common;
-using HeuristicLab.Hive;
-
-namespace HeuristicLab.Clients.Hive {
-  /// <summary>
-  /// Downloads and deserializes jobs. It avoids too many jobs beeing downloaded or deserialized at the same time to avoid memory problems
-  /// </summary>
-  public class ConcurrentJobDownloader<T> where T : class, IJob {
-    private bool abort = false;
-    // use semaphore to ensure only few concurrenct connections and few SerializedJob objects in memory
-    private Semaphore downloadSemaphore;
-    private Semaphore deserializeSemaphore;
-
-    public ConcurrentJobDownloader(int concurrentDownloads, int concurrentDeserializations) {
-      downloadSemaphore = new Semaphore(concurrentDownloads, concurrentDownloads);
-      deserializeSemaphore = new Semaphore(concurrentDeserializations, concurrentDeserializations);
-      TaskScheduler.UnobservedTaskException += new EventHandler<UnobservedTaskExceptionEventArgs>(TaskScheduler_UnobservedTaskException);
-    }
-
-    public void DownloadJob(Task job, Action<Task, T> onFinishedAction) {
-      Task<T> task = Task<TaskData>.Factory.StartNew((x) => DownloadJob(x), job.Id)
-                                     .ContinueWith((x) => DeserializeJob(x.Result));
-      task.ContinueWith((x) => OnJobFinished(job, x, onFinishedAction), TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnRanToCompletion);
-      task.ContinueWith((x) => OnJobFailed(job, x, onFinishedAction), TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnFaulted);
-    }
-
-    private void OnJobFinished(Task job, Task<T> task, Action<Task, T> onFinishedAction) {
-      onFinishedAction(job, task.Result);
-    }
-    private void OnJobFailed(Task job, Task<T> task, Action<Task, T> onFinishedAction) {
-      task.Exception.Flatten().Handle((e) => { return true; });
-      OnExceptionOccured(task.Exception.Flatten());
-      onFinishedAction(job, null);
-    }
-
-    protected TaskData DownloadJob(object jobId) {
-      downloadSemaphore.WaitOne();
-      deserializeSemaphore.WaitOne();
-      TaskData result;
-      try {
-        if (abort) return null;
-        result = ServiceLocator.Instance.CallHiveService(s => s.GetJobData((Guid)jobId));
-      }
-      finally {
-        downloadSemaphore.Release();
-      }
-      return result;
-    }
-
-    protected T DeserializeJob(TaskData jobData) {
-      try {
-        if (abort || jobData == null) return null;
-        Task job = ServiceLocator.Instance.CallHiveService(s => s.GetJob(jobData.TaskId));
-        if (job == null) return null;
-        var deserializedJob = PersistenceUtil.Deserialize<T>(jobData.Data);
-        jobData.Data = null; // reduce memory consumption.
-        return deserializedJob;
-      }
-      finally {
-        deserializeSemaphore.Release();
-      }
-    }
-
-    private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e) {
-      e.SetObserved(); // avoid crash of process because task crashes. first exception found is handled in Results property
-      OnExceptionOccured(new HiveException("Unobserved Exception in ConcurrentJobDownloader", e.Exception));
-    }
-
-    public event EventHandler<EventArgs<Exception>> ExceptionOccured;
-    private void OnExceptionOccured(Exception exception) {
-      var handler = ExceptionOccured;
-      if (handler != null) handler(this, new EventArgs<Exception>(exception));
-    }
-  }
-}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/ConcurrentJobDownloaderException.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/ConcurrentJobDownloaderException.cs	(revision 6723)
+++ 	(revision )
@@ -1,29 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-
-namespace HeuristicLab.Clients.Hive {
-  public class ConcurrentJobDownloaderException : Exception {
-    public ConcurrentJobDownloaderException(string message, Exception innerException)
-      : base(message, innerException) { }
-  }
-}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/ConcurrentTaskDownloader.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/ConcurrentTaskDownloader.cs	(revision 6725)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/ConcurrentTaskDownloader.cs	(revision 6725)
@@ -0,0 +1,99 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using HeuristicLab.Common;
+using HeuristicLab.Hive;
+
+namespace HeuristicLab.Clients.Hive {
+  /// <summary>
+  /// Downloads and deserializes jobs. It avoids too many jobs beeing downloaded or deserialized at the same time to avoid memory problems
+  /// </summary>
+  public class ConcurrentTaskDownloader<T> where T : class, ITask {
+    private bool abort = false;
+    // use semaphore to ensure only few concurrenct connections and few SerializedJob objects in memory
+    private Semaphore downloadSemaphore;
+    private Semaphore deserializeSemaphore;
+
+    public ConcurrentTaskDownloader(int concurrentDownloads, int concurrentDeserializations) {
+      downloadSemaphore = new Semaphore(concurrentDownloads, concurrentDownloads);
+      deserializeSemaphore = new Semaphore(concurrentDeserializations, concurrentDeserializations);
+      TaskScheduler.UnobservedTaskException += new EventHandler<UnobservedTaskExceptionEventArgs>(TaskScheduler_UnobservedTaskException);
+    }
+
+    public void DownloadJob(Task job, Action<Task, T> onFinishedAction) {
+      Task<T> task = Task<TaskData>.Factory.StartNew((x) => DownloadJob(x), job.Id)
+                                     .ContinueWith((x) => DeserializeJob(x.Result));
+      task.ContinueWith((x) => OnJobFinished(job, x, onFinishedAction), TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnRanToCompletion);
+      task.ContinueWith((x) => OnJobFailed(job, x, onFinishedAction), TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnFaulted);
+    }
+
+    private void OnJobFinished(Task job, Task<T> task, Action<Task, T> onFinishedAction) {
+      onFinishedAction(job, task.Result);
+    }
+    private void OnJobFailed(Task job, Task<T> task, Action<Task, T> onFinishedAction) {
+      task.Exception.Flatten().Handle((e) => { return true; });
+      OnExceptionOccured(task.Exception.Flatten());
+      onFinishedAction(job, null);
+    }
+
+    protected TaskData DownloadJob(object jobId) {
+      downloadSemaphore.WaitOne();
+      deserializeSemaphore.WaitOne();
+      TaskData result;
+      try {
+        if (abort) return null;
+        result = ServiceLocator.Instance.CallHiveService(s => s.GetJobData((Guid)jobId));
+      }
+      finally {
+        downloadSemaphore.Release();
+      }
+      return result;
+    }
+
+    protected T DeserializeJob(TaskData jobData) {
+      try {
+        if (abort || jobData == null) return null;
+        Task job = ServiceLocator.Instance.CallHiveService(s => s.GetJob(jobData.TaskId));
+        if (job == null) return null;
+        var deserializedJob = PersistenceUtil.Deserialize<T>(jobData.Data);
+        jobData.Data = null; // reduce memory consumption.
+        return deserializedJob;
+      }
+      finally {
+        deserializeSemaphore.Release();
+      }
+    }
+
+    private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e) {
+      e.SetObserved(); // avoid crash of process because task crashes. first exception found is handled in Results property
+      OnExceptionOccured(new HiveException("Unobserved Exception in ConcurrentTaskDownloader", e.Exception));
+    }
+
+    public event EventHandler<EventArgs<Exception>> ExceptionOccured;
+    private void OnExceptionOccured(Exception exception) {
+      var handler = ExceptionOccured;
+      if (handler != null) handler(this, new EventArgs<Exception>(exception));
+    }
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/ConcurrentTaskDownloaderException.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/ConcurrentTaskDownloaderException.cs	(revision 6725)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/ConcurrentTaskDownloaderException.cs	(revision 6725)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+
+namespace HeuristicLab.Clients.Hive {
+  public class ConcurrentTaskDownloaderException : Exception {
+    public ConcurrentTaskDownloaderException(string message, Exception innerException)
+      : base(message, innerException) { }
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/Exceptions/AddJobToHiveException.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/Exceptions/AddJobToHiveException.cs	(revision 6723)
+++ 	(revision )
@@ -1,28 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-
-namespace HeuristicLab.Clients.Hive {
-  class AddJobToHiveException : Exception {
-    public AddJobToHiveException(string message) : base(message) { }
-  }
-}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/Exceptions/AddTaskToHiveException.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/Exceptions/AddTaskToHiveException.cs	(revision 6725)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/Exceptions/AddTaskToHiveException.cs	(revision 6725)
@@ -0,0 +1,28 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+
+namespace HeuristicLab.Clients.Hive {
+  class AddTaskToHiveException : Exception {
+    public AddTaskToHiveException(string message) : base(message) { }
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/Exceptions/JobResultPollingException.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/Exceptions/JobResultPollingException.cs	(revision 6723)
+++ 	(revision )
@@ -1,28 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-
-namespace HeuristicLab.Clients.Hive {
-  class JobResultPollingException : Exception {
-    public JobResultPollingException(string message) : base(message) { }
-  }
-}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/Exceptions/TaskResultPollingException.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/Exceptions/TaskResultPollingException.cs	(revision 6725)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/Exceptions/TaskResultPollingException.cs	(revision 6725)
@@ -0,0 +1,28 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+
+namespace HeuristicLab.Clients.Hive {
+  class TaskResultPollingException : Exception {
+    public TaskResultPollingException(string message) : base(message) { }
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HeuristicLab.Clients.Hive-3.3.csproj
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HeuristicLab.Clients.Hive-3.3.csproj	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HeuristicLab.Clients.Hive-3.3.csproj	(revision 6725)
@@ -113,6 +113,6 @@
   <ItemGroup>
     <Compile Include="HiveClient.cs" />
-    <Compile Include="Jobs\ItemJob.cs" />
-    <Compile Include="RefreshableHiveExperiment.cs" />
+    <Compile Include="Tasks\ItemTask.cs" />
+    <Compile Include="RefreshableJob.cs" />
     <Compile Include="ServiceClients\HiveExperimentPermission.cs" />
     <Compile Include="StateLogList.cs" />
@@ -122,23 +122,23 @@
     <None Include="app.config" />
     <None Include="HeuristicLabClientsHivePlugin.cs.frame" />
-    <Compile Include="Exceptions\AddJobToHiveException.cs" />
-    <Compile Include="Exceptions\JobResultPollingException.cs" />
+    <Compile Include="Exceptions\AddTaskToHiveException.cs" />
+    <Compile Include="Exceptions\TaskResultPollingException.cs" />
     <Compile Include="Exceptions\OptimizerNotFoundException.cs" />
-    <Compile Include="ConcurrentJobDownloader.cs" />
-    <Compile Include="HiveJobs\EngineHiveJob.cs" />
+    <Compile Include="ConcurrentTaskDownloader.cs" />
+    <Compile Include="HiveJobs\EngineHiveTask.cs" />
     <Compile Include="Exceptions\HiveException.cs" />
-    <Compile Include="HiveJobDownloader.cs" />
-    <Compile Include="ConcurrentJobDownloaderException.cs" />
+    <Compile Include="TaskDownloader.cs" />
+    <Compile Include="ConcurrentTaskDownloaderException.cs" />
     <Compile Include="TreeView\IItemTree.cs" />
     <Compile Include="TreeView\IItemTreeAction.cs" />
-    <Compile Include="HiveJobs\OptimizerHiveJob.cs">
+    <Compile Include="HiveJobs\OptimizerHiveTask.cs">
       <SubType>Code</SubType>
     </Compile>
     <Compile Include="Exceptions\ResourceNotFoundException.cs" />
     <Compile Include="IServiceLocator.cs" />
-    <Compile Include="Jobs\EngineJob.cs" />
-    <Compile Include="Jobs\OptimizerJob.cs" />
+    <Compile Include="Tasks\EngineTask.cs" />
+    <Compile Include="Tasks\OptimizerTask.cs" />
     <Compile Include="HeuristicLabClientsHivePlugin.cs" />
-    <Compile Include="HiveJobs\HiveJob.cs" />
+    <Compile Include="HiveJobs\HiveTask.cs" />
     <Compile Include="JobResultPoller.cs" />
     <Compile Include="Util\PersistenceUtil.cs" />
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HiveClient.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HiveClient.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HiveClient.cs	(revision 6725)
@@ -45,10 +45,10 @@
 
     #region Properties
-    private ItemCollection<RefreshableHiveExperiment> hiveExperiments;
-    public ItemCollection<RefreshableHiveExperiment> HiveExperiments {
-      get { return hiveExperiments; }
+    private ItemCollection<RefreshableJob> jobs;
+    public ItemCollection<RefreshableJob> Jobs {
+      get { return jobs; }
       set {
-        if (value != hiveExperiments) {
-          hiveExperiments = value;
+        if (value != jobs) {
+          jobs = value;
           OnHiveExperimentsChanged();
         }
@@ -84,6 +84,6 @@
         this.IsAllowedPrivileged = ServiceLocator.Instance.CallHiveService((s) => s.IsAllowedPrivileged());
 
-        var oldExperiments = hiveExperiments ?? new ItemCollection<RefreshableHiveExperiment>();
-        hiveExperiments = new HiveItemCollection<RefreshableHiveExperiment>();
+        var oldExperiments = jobs ?? new ItemCollection<RefreshableJob>();
+        jobs = new HiveItemCollection<RefreshableJob>();
         var experimentsLoaded = ServiceLocator.Instance.CallHiveService<IEnumerable<Job>>(s => s.GetHiveExperiments());
 
@@ -92,10 +92,10 @@
           if (hiveExperiment == null) {
             // new
-            hiveExperiments.Add(new RefreshableHiveExperiment(he) { IsAllowedPrivileged = this.isAllowedPrivileged });
+            jobs.Add(new RefreshableJob(he) { IsAllowedPrivileged = this.isAllowedPrivileged });
           } else {
             // update
-            hiveExperiment.HiveExperiment = he;
+            hiveExperiment.Job = he;
             hiveExperiment.IsAllowedPrivileged = this.isAllowedPrivileged;
-            hiveExperiments.Add(hiveExperiment);
+            jobs.Add(hiveExperiment);
           }
         }
@@ -104,5 +104,5 @@
           if (experiment.Id == Guid.Empty) {
             // experiment not uploaded... keep
-            hiveExperiments.Add(experiment);
+            jobs.Add(experiment);
           } else {
             experiment.RefreshAutomatically = false; // stop results polling
@@ -111,5 +111,5 @@
       }
       catch {
-        hiveExperiments = null;
+        jobs = null;
         throw;
       }
@@ -138,6 +138,6 @@
     public static void Store(IHiveItem item, CancellationToken cancellationToken) {
       if (item.Id == Guid.Empty) {
-        if (item is RefreshableHiveExperiment) {
-          HiveClient.Instance.UploadExperiment((RefreshableHiveExperiment)item, cancellationToken);
+        if (item is RefreshableJob) {
+          HiveClient.Instance.UploadExperiment((RefreshableJob)item, cancellationToken);
         }
         if (item is JobPermission) {
@@ -178,5 +178,5 @@
       if (item is Job)
         ServiceLocator.Instance.CallHiveService(s => s.DeleteHiveExperiment(item.Id));
-      if (item is RefreshableHiveExperiment)
+      if (item is RefreshableJob)
         ServiceLocator.Instance.CallHiveService(s => s.DeleteHiveExperiment(item.Id));
       if (item is JobPermission) {
@@ -206,18 +206,18 @@
     #endregion
 
-    public static void StartExperiment(Action<Exception> exceptionCallback, RefreshableHiveExperiment refreshableHiveExperiment, CancellationToken cancellationToken) {
+    public static void StartExperiment(Action<Exception> exceptionCallback, RefreshableJob refreshableJob, CancellationToken cancellationToken) {
       HiveClient.StoreAsync(
         new Action<Exception>((Exception ex) => {
-          refreshableHiveExperiment.ExecutionState = ExecutionState.Prepared;
+          refreshableJob.ExecutionState = ExecutionState.Prepared;
           exceptionCallback(ex);
-        }), refreshableHiveExperiment, cancellationToken);
-      refreshableHiveExperiment.ExecutionState = ExecutionState.Started;
-    }
-
-    public static void PauseExperiment(RefreshableHiveExperiment refreshableHiveExperiment) {
+        }), refreshableJob, cancellationToken);
+      refreshableJob.ExecutionState = ExecutionState.Started;
+    }
+
+    public static void PauseExperiment(RefreshableJob refreshableHiveExperiment) {
       ServiceLocator.Instance.CallHiveService(service => {
-        foreach (HiveJob job in refreshableHiveExperiment.GetAllHiveJobs()) {
-          if (job.Job.State != TaskState.Finished && job.Job.State != TaskState.Aborted && job.Job.State != TaskState.Failed)
-            service.PauseJob(job.Job.Id);
+        foreach (HiveTask job in refreshableHiveExperiment.GetAllHiveJobs()) {
+          if (job.Task.State != TaskState.Finished && job.Task.State != TaskState.Aborted && job.Task.State != TaskState.Failed)
+            service.PauseJob(job.Task.Id);
         }
       });
@@ -225,9 +225,9 @@
     }
 
-    public static void StopExperiment(RefreshableHiveExperiment refreshableHiveExperiment) {
+    public static void StopExperiment(RefreshableJob refreshableJob) {
       ServiceLocator.Instance.CallHiveService(service => {
-        foreach (HiveJob job in refreshableHiveExperiment.GetAllHiveJobs()) {
-          if (job.Job.State != TaskState.Finished && job.Job.State != TaskState.Aborted && job.Job.State != TaskState.Failed)
-            service.StopJob(job.Job.Id);
+        foreach (HiveTask job in refreshableJob.GetAllHiveJobs()) {
+          if (job.Task.State != TaskState.Finished && job.Task.State != TaskState.Aborted && job.Task.State != TaskState.Failed)
+            service.StopJob(job.Task.Id);
         }
       });
@@ -239,10 +239,10 @@
     private static object jobCountLocker = new object();
     private static object pluginLocker = new object();
-    private void UploadExperiment(RefreshableHiveExperiment refreshableHiveExperiment, CancellationToken cancellationToken) {
+    private void UploadExperiment(RefreshableJob refreshableJob, CancellationToken cancellationToken) {
       try {
-        refreshableHiveExperiment.Progress = new Progress("Connecting to server...");
-        refreshableHiveExperiment.IsProgressing = true;
-
-        IEnumerable<string> resourceNames = ToResourceNameList(refreshableHiveExperiment.HiveExperiment.ResourceNames);
+        refreshableJob.Progress = new Progress("Connecting to server...");
+        refreshableJob.IsProgressing = true;
+
+        IEnumerable<string> resourceNames = ToResourceNameList(refreshableJob.Job.ResourceNames);
         var resourceIds = new List<Guid>();
         foreach (var resourceName in resourceNames) {
@@ -254,22 +254,22 @@
         }
 
-        foreach (OptimizerHiveJob hiveJob in refreshableHiveExperiment.HiveJobs.OfType<OptimizerHiveJob>()) {
+        foreach (OptimizerHiveTask hiveJob in refreshableJob.HiveJobs.OfType<OptimizerHiveTask>()) {
           hiveJob.SetIndexInParentOptimizerList(null);
         }
 
-        // upload Job
-        refreshableHiveExperiment.Progress.Status = "Uploading Job...";
-        refreshableHiveExperiment.HiveExperiment.Id = ServiceLocator.Instance.CallHiveService((s) => s.AddHiveExperiment(refreshableHiveExperiment.HiveExperiment));
-        bool isPrivileged = refreshableHiveExperiment.HiveExperiment.IsPrivileged;
-        refreshableHiveExperiment.HiveExperiment = ServiceLocator.Instance.CallHiveService((s) => s.GetHiveExperiment(refreshableHiveExperiment.HiveExperiment.Id)); // update owner and permissions
-        refreshableHiveExperiment.HiveExperiment.IsPrivileged = isPrivileged;
-        cancellationToken.ThrowIfCancellationRequested();
-
-        int totalJobCount = refreshableHiveExperiment.GetAllHiveJobs().Count();
+        // upload Task
+        refreshableJob.Progress.Status = "Uploading Task...";
+        refreshableJob.Job.Id = ServiceLocator.Instance.CallHiveService((s) => s.AddHiveExperiment(refreshableJob.Job));
+        bool isPrivileged = refreshableJob.Job.IsPrivileged;
+        refreshableJob.Job = ServiceLocator.Instance.CallHiveService((s) => s.GetHiveExperiment(refreshableJob.Job.Id)); // update owner and permissions
+        refreshableJob.Job.IsPrivileged = isPrivileged;
+        cancellationToken.ThrowIfCancellationRequested();
+
+        int totalJobCount = refreshableJob.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.Progress.Status = "Uploading plugins...";
+        refreshableJob.Progress.Status = "Uploading plugins...";
         this.OnlinePlugins = ServiceLocator.Instance.CallHiveService((s) => s.GetPlugins());
         this.AlreadyUploadedPlugins = new List<Plugin>();
@@ -278,15 +278,15 @@
         cancellationToken.ThrowIfCancellationRequested();
 
-        if (refreshableHiveExperiment.RefreshAutomatically) refreshableHiveExperiment.StartResultPolling();
+        if (refreshableJob.RefreshAutomatically) refreshableJob.StartResultPolling();
 
         // upload jobs
-        refreshableHiveExperiment.Progress.Status = "Uploading jobs...";
+        refreshableJob.Progress.Status = "Uploading jobs...";
 
         var tasks = new List<TS.Task>();
-        foreach (HiveJob hiveJob in refreshableHiveExperiment.HiveJobs) {
+        foreach (HiveTask hiveJob in refreshableJob.HiveJobs) {
           tasks.Add(TS.Task.Factory.StartNew((hj) => {
-            UploadJobWithChildren(refreshableHiveExperiment.Progress, (HiveJob)hj, null, resourceIds, jobCount, totalJobCount, configFilePlugin.Id, refreshableHiveExperiment.HiveExperiment.Id, refreshableHiveExperiment.Log, refreshableHiveExperiment.HiveExperiment.IsPrivileged, cancellationToken);
+            UploadJobWithChildren(refreshableJob.Progress, (HiveTask)hj, null, resourceIds, jobCount, totalJobCount, configFilePlugin.Id, refreshableJob.Job.Id, refreshableJob.Log, refreshableJob.Job.IsPrivileged, cancellationToken);
           }, hiveJob)
-          .ContinueWith((x) => refreshableHiveExperiment.Log.LogException(x.Exception), TaskContinuationOptions.OnlyOnFaulted));
+          .ContinueWith((x) => refreshableJob.Log.LogException(x.Exception), TaskContinuationOptions.OnlyOnFaulted));
         }
         try {
@@ -296,8 +296,8 @@
           if (!ae.InnerExceptions.All(e => e is TaskCanceledException)) throw ae; // for some reason the WaitAll throws a AggregateException containg a TaskCanceledException. i don't know where it comes from, however the tasks all finish properly, so for now just ignore it
         }
-        refreshableHiveExperiment.HiveExperiment.Modified = false;
+        refreshableJob.Job.Modified = false;
       }
       finally {
-        refreshableHiveExperiment.IsProgressing = false;
+        refreshableJob.IsProgressing = false;
       }
     }
@@ -331,8 +331,8 @@
 
     /// <summary>
-    /// Uploads the given job and all its child-jobs while setting the proper parentJobId values for the childs
+    /// Uploads the given task and all its child-jobs while setting the proper parentJobId values for the childs
     /// </summary>
-    /// <param name="parentHiveJob">shall be null if its the root job</param>
-    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) {
+    /// <param name="parentHiveTask">shall be null if its the root task</param>
+    private void UploadJobWithChildren(IProgress progress, HiveTask hiveJob, HiveTask parentHiveJob, IEnumerable<Guid> groups, int[] jobCount, int totalJobCount, Guid configPluginId, Guid hiveExperimentId, ILog log, bool isPrivileged, CancellationToken cancellationToken) {
       jobUploadSemaphore.WaitOne();
       bool semaphoreReleased = false;
@@ -345,12 +345,12 @@
         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);
+        if (hiveJob.ItemTask.ComputeInParallel && (hiveJob.ItemTask.Item is Optimization.Experiment || hiveJob.ItemTask.Item is Optimization.BatchRun)) {
+          hiveJob.Task.IsParentTask = true;
+          hiveJob.Task.FinishWhenChildJobsFinished = true;
+          jobData = hiveJob.GetAsTaskData(true, out plugins);
         } else {
-          hiveJob.Job.IsParentJob = false;
-          hiveJob.Job.FinishWhenChildJobsFinished = false;
-          jobData = hiveJob.GetAsJobData(false, out plugins);
+          hiveJob.Task.IsParentTask = false;
+          hiveJob.Task.FinishWhenChildJobsFinished = false;
+          jobData = hiveJob.GetAsTaskData(false, out plugins);
         }
         cancellationToken.ThrowIfCancellationRequested();
@@ -359,36 +359,36 @@
           if (!cancellationToken.IsCancellationRequested) {
             lock (pluginLocker) {
-              ServiceLocator.Instance.CallHiveService((s) => hiveJob.Job.PluginsNeededIds = PluginUtil.GetPluginDependencies(s, this.onlinePlugins, this.alreadyUploadedPlugins, plugins));
+              ServiceLocator.Instance.CallHiveService((s) => hiveJob.Task.PluginsNeededIds = PluginUtil.GetPluginDependencies(s, this.onlinePlugins, this.alreadyUploadedPlugins, plugins));
             }
           }
         }, -1, "Failed to upload plugins");
         cancellationToken.ThrowIfCancellationRequested();
-        hiveJob.Job.PluginsNeededIds.Add(configPluginId);
-        hiveJob.Job.JobId = hiveExperimentId;
-        hiveJob.Job.IsPrivileged = isPrivileged;
-
-        log.LogMessage(string.Format("Uploading job ({0} kb, {1} objects)", jobData.Data.Count() / 1024, hiveJob.ItemJob.GetObjectGraphObjects().Count()));
+        hiveJob.Task.PluginsNeededIds.Add(configPluginId);
+        hiveJob.Task.JobId = hiveExperimentId;
+        hiveJob.Task.IsPrivileged = isPrivileged;
+
+        log.LogMessage(string.Format("Uploading task ({0} kb, {1} objects)", jobData.Data.Count() / 1024, hiveJob.ItemTask.GetObjectGraphObjects().Count()));
         TryAndRepeat(() => {
           if (!cancellationToken.IsCancellationRequested) {
             if (parentHiveJob != null) {
-              hiveJob.Job.Id = ServiceLocator.Instance.CallHiveService((s) => s.AddChildJob(parentHiveJob.Job.Id, hiveJob.Job, jobData));
+              hiveJob.Task.Id = ServiceLocator.Instance.CallHiveService((s) => s.AddChildJob(parentHiveJob.Task.Id, hiveJob.Task, jobData));
             } else {
-              hiveJob.Job.Id = ServiceLocator.Instance.CallHiveService((s) => s.AddJob(hiveJob.Job, jobData, groups.ToList()));
+              hiveJob.Task.Id = ServiceLocator.Instance.CallHiveService((s) => s.AddJob(hiveJob.Task, jobData, groups.ToList()));
             }
           }
-        }, 50, "Failed to add job", log);
+        }, 50, "Failed to add task", log);
         cancellationToken.ThrowIfCancellationRequested();
 
         lock (jobCountLocker) {
           progress.ProgressValue = (double)jobCount[0] / totalJobCount;
-          progress.Status = string.Format("Uploaded job ({0} of {1})", jobCount[0], totalJobCount);
+          progress.Status = string.Format("Uploaded task ({0} of {1})", jobCount[0], totalJobCount);
         }
 
         var tasks = new List<TS.Task>();
-        foreach (HiveJob child in hiveJob.ChildHiveJobs) {
+        foreach (HiveTask child in hiveJob.ChildHiveTasks) {
           tasks.Add(TS.Task.Factory.StartNew((tuple) => {
-            var arguments = (Tuple<HiveJob, HiveJob>)tuple;
+            var arguments = (Tuple<HiveTask, HiveTask>)tuple;
             UploadJobWithChildren(progress, arguments.Item1, arguments.Item2, groups, jobCount, totalJobCount, configPluginId, hiveExperimentId, log, isPrivileged, cancellationToken);
-          }, new Tuple<HiveJob, HiveJob>(child, hiveJob))
+          }, new Tuple<HiveTask, HiveTask>(child, hiveJob))
           .ContinueWith((x) => log.LogException(x.Exception), TaskContinuationOptions.OnlyOnFaulted));
         }
@@ -408,25 +408,25 @@
 
     #region Download Experiment
-    public static void LoadExperiment(RefreshableHiveExperiment refreshableHiveExperiment) {
-      var hiveExperiment = refreshableHiveExperiment.HiveExperiment;
-      refreshableHiveExperiment.Progress = new Progress();
+    public static void LoadExperiment(RefreshableJob refreshableJob) {
+      var hiveExperiment = refreshableJob.Job;
+      refreshableJob.Progress = new Progress();
 
       try {
-        refreshableHiveExperiment.IsProgressing = true;
+        refreshableJob.IsProgressing = true;
         int totalJobCount = 0;
         IEnumerable<LightweightTask> allJobs;
 
-        refreshableHiveExperiment.Progress.Status = "Connecting to Server...";
-        // fetch all Task objects to create the full tree of tree of HiveJob objects
-        refreshableHiveExperiment.Progress.Status = "Downloading list of jobs...";
+        refreshableJob.Progress.Status = "Connecting to Server...";
+        // fetch all Task objects to create the full tree of tree of HiveTask objects
+        refreshableJob.Progress.Status = "Downloading list of jobs...";
         allJobs = ServiceLocator.Instance.CallHiveService(s => s.GetLightweightExperimentJobs(hiveExperiment.Id));
         totalJobCount = allJobs.Count();
 
-        HiveJobDownloader downloader = new HiveJobDownloader(allJobs.Select(x => x.Id));
+        TaskDownloader downloader = new TaskDownloader(allJobs.Select(x => x.Id));
         downloader.StartAsync();
 
         while (!downloader.IsFinished) {
-          refreshableHiveExperiment.Progress.ProgressValue = downloader.FinishedCount / (double)totalJobCount;
-          refreshableHiveExperiment.Progress.Status = string.Format("Downloading/deserializing jobs... ({0}/{1} finished)", downloader.FinishedCount, totalJobCount);
+          refreshableJob.Progress.ProgressValue = downloader.FinishedCount / (double)totalJobCount;
+          refreshableJob.Progress.Status = string.Format("Downloading/deserializing jobs... ({0}/{1} finished)", downloader.FinishedCount, totalJobCount);
           Thread.Sleep(500);
 
@@ -435,33 +435,33 @@
           }
         }
-        IDictionary<Guid, HiveJob> allHiveJobs = downloader.Results;
-
-        refreshableHiveExperiment.HiveJobs = new ItemCollection<HiveJob>(allHiveJobs.Values.Where(x => !x.Job.ParentTaskId.HasValue));
-
-        if (refreshableHiveExperiment.IsFinished()) {
-          refreshableHiveExperiment.ExecutionState = Core.ExecutionState.Stopped;
+        IDictionary<Guid, HiveTask> allHiveJobs = downloader.Results;
+
+        refreshableJob.HiveJobs = new ItemCollection<HiveTask>(allHiveJobs.Values.Where(x => !x.Task.ParentTaskId.HasValue));
+
+        if (refreshableJob.IsFinished()) {
+          refreshableJob.ExecutionState = Core.ExecutionState.Stopped;
         } else {
-          refreshableHiveExperiment.ExecutionState = Core.ExecutionState.Started;
-        }
-
-        // build child-job tree
-        foreach (HiveJob hiveJob in refreshableHiveExperiment.HiveJobs) {
+          refreshableJob.ExecutionState = Core.ExecutionState.Started;
+        }
+
+        // build child-task tree
+        foreach (HiveTask hiveJob in refreshableJob.HiveJobs) {
           BuildHiveJobTree(hiveJob, allJobs, allHiveJobs);
         }
 
-        refreshableHiveExperiment.OnLoaded();
+        refreshableJob.OnLoaded();
       }
       finally {
-        refreshableHiveExperiment.IsProgressing = false;
-      }
-    }
-
-    private static void BuildHiveJobTree(HiveJob parentHiveJob, IEnumerable<LightweightTask> allJobs, IDictionary<Guid, HiveJob> allHiveJobs) {
+        refreshableJob.IsProgressing = false;
+      }
+    }
+
+    private static void BuildHiveJobTree(HiveTask parentHiveJob, IEnumerable<LightweightTask> allJobs, IDictionary<Guid, HiveTask> allHiveJobs) {
       IEnumerable<LightweightTask> childJobs = from job in allJobs
-                                               where job.ParentTaskId.HasValue && job.ParentTaskId.Value == parentHiveJob.Job.Id
+                                               where job.ParentTaskId.HasValue && job.ParentTaskId.Value == parentHiveJob.Task.Id
                                                orderby job.DateCreated ascending
                                                select job;
       foreach (LightweightTask job in childJobs) {
-        HiveJob childHiveJob = allHiveJobs[job.Id];
+        HiveTask childHiveJob = allHiveJobs[job.Id];
         parentHiveJob.AddChildHiveJob(childHiveJob);
         BuildHiveJobTree(childHiveJob, allJobs, allHiveJobs);
@@ -481,8 +481,8 @@
     }
 
-    public static ItemJob LoadItemJob(Guid jobId) {
+    public static ItemTask LoadItemJob(Guid jobId) {
       TaskData jobData = ServiceLocator.Instance.CallHiveService(s => s.GetJobData(jobId));
       try {
-        return PersistenceUtil.Deserialize<ItemJob>(jobData.Data);
+        return PersistenceUtil.Deserialize<ItemTask>(jobData.Data);
       }
       catch {
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HiveJobDownloader.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HiveJobDownloader.cs	(revision 6723)
+++ 	(revision )
@@ -1,105 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using HeuristicLab.Clients.Hive.Jobs;
-using HeuristicLab.Common;
-
-namespace HeuristicLab.Clients.Hive {
-  public class HiveJobDownloader {
-    private IEnumerable<Guid> jobIds;
-    private ConcurrentJobDownloader<ItemJob> jobDownloader;
-    private IDictionary<Guid, HiveJob> results;
-    private bool exceptionOccured = false;
-    private Exception currentException;
-
-    public bool IsFinished {
-      get {
-        return results.Count == jobIds.Count();
-      }
-    }
-
-    public bool IsFaulted {
-      get {
-        return exceptionOccured;
-      }
-    }
-
-    public Exception Exception {
-      get {
-        return currentException;
-      }
-    }
-    
-    public int FinishedCount {
-      get {
-        return results.Count;
-      }
-    }
-
-    public IDictionary<Guid, HiveJob> Results {
-      get {
-        return results;
-      }
-    }
-
-    public HiveJobDownloader(IEnumerable<Guid> jobIds) {
-      this.jobIds = jobIds;
-      this.jobDownloader = new ConcurrentJobDownloader<ItemJob>(2, 2);
-      this.jobDownloader.ExceptionOccured += new EventHandler<EventArgs<Exception>>(jobDownloader_ExceptionOccured);
-      this.results = new Dictionary<Guid, HiveJob>();
-    }
-    
-    public void StartAsync() {
-      foreach (Guid jobId in jobIds) {
-        Task job = ServiceLocator.Instance.CallHiveService(s => s.GetJob(jobId));
-
-        jobDownloader.DownloadJob(job,
-          (localJob, itemJob) => {
-            if (localJob != null && itemJob != null) {
-              HiveJob hiveJob;
-              if (itemJob is OptimizerJob) {
-                hiveJob = new OptimizerHiveJob((OptimizerJob)itemJob);
-              } else {
-                hiveJob = new HiveJob(itemJob, true);
-              }
-              hiveJob.Job = localJob;
-              this.results.Add(localJob.Id, hiveJob);
-            }
-          });
-      }      
-    }
-
-    private void jobDownloader_ExceptionOccured(object sender, EventArgs<Exception> e) {
-      OnExceptionOccured(e.Value);
-    }
-
-    public event EventHandler<EventArgs<Exception>> ExceptionOccured;
-    private void OnExceptionOccured(Exception exception) {
-      this.exceptionOccured = true;
-      this.currentException = exception;
-      var handler = ExceptionOccured;
-      if (handler != null) handler(this, new EventArgs<Exception>(exception));
-    }
-  }
-}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HiveJobs/EngineHiveJob.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HiveJobs/EngineHiveJob.cs	(revision 6723)
+++ 	(revision )
@@ -1,79 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using HeuristicLab.Common;
-using HeuristicLab.Core;
-using HeuristicLab.PluginInfrastructure;
-
-namespace HeuristicLab.Clients.Hive {
-  public class EngineHiveJob : HiveJob<EngineJob> {
-    private IScope parentScopeClone;
-
-    #region Constructors and cloning
-    public EngineHiveJob() { }
-    public EngineHiveJob(EngineJob engineJob, IScope parentScopeClone)
-      : base(engineJob) {
-      this.parentScopeClone = parentScopeClone;
-    }
-
-    protected EngineHiveJob(EngineHiveJob original, Cloner cloner)
-      : base(original, cloner) {
-      this.parentScopeClone = cloner.Clone(original.parentScopeClone);
-    }
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new EngineHiveJob(this, cloner);
-    }
-    #endregion
-
-    public override TaskData GetAsJobData(bool withoutChildOptimizers, out List<IPluginDescription> plugins) {
-      plugins = new List<IPluginDescription>();
-      if (this.itemJob == null)
-        return null;
-
-      TaskData jobData = new TaskData();
-      IEnumerable<Type> usedTypes;
-
-      // clone operation and remove unnecessary scopes; don't do this earlier to avoid memory problems
-      //lock (locker) {
-        ((IAtomicOperation)ItemJob.InitialOperation).Scope.Parent = parentScopeClone;
-        ItemJob.InitialOperation = (IOperation)ItemJob.InitialOperation.Clone();
-        ((IAtomicOperation)ItemJob.InitialOperation).Scope.ClearParentScopes();
-        jobData.Data = PersistenceUtil.Serialize(ItemJob, out usedTypes);
-      //}
-
-      // add type objects from object graph to work around ticket #1527
-      var typeObjects = ItemJob.GetObjectGraphObjects().OfType<Type>();
-      usedTypes = new List<Type>(usedTypes).Union(typeObjects);
-
-      PluginUtil.CollectDeclaringPlugins(plugins, usedTypes);
-      
-      return jobData;
-    }
-
-    public override void ClearData() {
-      base.ClearData();
-      this.ItemJob.InitialOperation = null;
-    }
-  }
-}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HiveJobs/EngineHiveTask.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HiveJobs/EngineHiveTask.cs	(revision 6725)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HiveJobs/EngineHiveTask.cs	(revision 6725)
@@ -0,0 +1,79 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.Clients.Hive {
+  public class EngineHiveTask : HiveTask<EngineTask> {
+    private IScope parentScopeClone;
+
+    #region Constructors and cloning
+    public EngineHiveTask() { }
+    public EngineHiveTask(EngineTask engineJob, IScope parentScopeClone)
+      : base(engineJob) {
+      this.parentScopeClone = parentScopeClone;
+    }
+
+    protected EngineHiveTask(EngineHiveTask original, Cloner cloner)
+      : base(original, cloner) {
+      this.parentScopeClone = cloner.Clone(original.parentScopeClone);
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new EngineHiveTask(this, cloner);
+    }
+    #endregion
+
+    public override TaskData GetAsTaskData(bool withoutChildOptimizers, out List<IPluginDescription> plugins) {
+      plugins = new List<IPluginDescription>();
+      if (this.itemTask == null)
+        return null;
+
+      TaskData jobData = new TaskData();
+      IEnumerable<Type> usedTypes;
+
+      // clone operation and remove unnecessary scopes; don't do this earlier to avoid memory problems
+      //lock (locker) {
+        ((IAtomicOperation)ItemTask.InitialOperation).Scope.Parent = parentScopeClone;
+        ItemTask.InitialOperation = (IOperation)ItemTask.InitialOperation.Clone();
+        ((IAtomicOperation)ItemTask.InitialOperation).Scope.ClearParentScopes();
+        jobData.Data = PersistenceUtil.Serialize(ItemTask, out usedTypes);
+      //}
+
+      // add type objects from object graph to work around ticket #1527
+      var typeObjects = ItemTask.GetObjectGraphObjects().OfType<Type>();
+      usedTypes = new List<Type>(usedTypes).Union(typeObjects);
+
+      PluginUtil.CollectDeclaringPlugins(plugins, usedTypes);
+      
+      return jobData;
+    }
+
+    public override void ClearData() {
+      base.ClearData();
+      this.ItemTask.InitialOperation = null;
+    }
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HiveJobs/HiveJob.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HiveJobs/HiveJob.cs	(revision 6723)
+++ 	(revision )
@@ -1,526 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Drawing;
-using System.Linq;
-using System.Threading;
-using HeuristicLab.Collections;
-using HeuristicLab.Common;
-using HeuristicLab.Core;
-using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
-using HeuristicLab.PluginInfrastructure;
-
-namespace HeuristicLab.Clients.Hive {
-
-  [Item("Hive Task", "Represents a hive job.")]
-  [StorableClass]
-  public class HiveJob : NamedItem, IItemTree<HiveJob> {
-    protected static object locker = new object();
-    protected ReaderWriterLockSlim childHiveJobsLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
-
-    public override Image ItemImage {
-      get {
-        if (job.Id == Guid.Empty) { // not yet uploaded
-          return HeuristicLab.Common.Resources.VSImageLibrary.Event;
-        } else {
-          if (job.State == TaskState.Waiting) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutablePrepared;
-          else if (job.State == TaskState.Calculating) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutableStarted;
-          else if (job.State == TaskState.Transferring) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutableStarted;
-          else if (job.State == TaskState.Paused) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutablePaused;
-          else if (job.State == TaskState.Aborted) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutableStopped;
-          else if (job.State == TaskState.Failed) return HeuristicLab.Common.Resources.VSImageLibrary.Error;
-          else if (job.State == TaskState.Finished) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutableStopped;
-          else return HeuristicLab.Common.Resources.VSImageLibrary.Event;
-        }
-      }
-    }
-
-    [Storable]
-    protected Task job;
-    public Task Job {
-      get { return job; }
-      set {
-        if (job != value) {
-          DeregisterJobEvents();
-          job = value;
-          RegisterJobEvents();
-          IsFinishedJobDownloaded = false;
-          OnJobChanged();
-          OnToStringChanged();
-          OnItemImageChanged();
-        }
-
-      }
-    }
-
-    [Storable]
-    protected ItemJob itemJob;
-    public ItemJob ItemJob {
-      get { return itemJob; }
-      set {
-        if (itemJob != null && syncJobsWithOptimizers) {
-          this.childHiveJobs.Clear();
-        }
-        if (itemJob != value) {
-          DergisterItemJobEvents();
-          itemJob = value;
-          RegisterItemJobEvents();
-          OnItemJobChanged();
-          IsFinishedJobDownloaded = true;
-        }
-      }
-    }
-
-    // job downloaded since last status change
-    [Storable]
-    private bool isFinishedJobDownloaded = false;
-    public bool IsFinishedJobDownloaded {
-      get { return isFinishedJobDownloaded; }
-      set {
-        if (value != isFinishedJobDownloaded) {
-          this.isFinishedJobDownloaded = value;
-          OnIsFinishedJobDownloadedChanged();
-        }
-      }
-    }
-
-    public bool IsDownloading { get; set; }
-
-    // if true, all control buttons should be enabled. otherwise disabled
-    private bool isControllable = true;
-    public bool IsControllable {
-      get { return isControllable; }
-      set {
-        if (value != isControllable) {
-          isControllable = value;
-          OnIsControllableChanged();
-          childHiveJobsLock.EnterReadLock();
-          try {
-            foreach (var hiveJob in childHiveJobs) {
-              hiveJob.IsControllable = value;
-            }
-          }
-          finally {
-            childHiveJobsLock.ExitReadLock();
-          }
-        }
-      }
-    }
-
-    [Storable]
-    protected ItemList<HiveJob> childHiveJobs;
-    public virtual ReadOnlyItemList<HiveJob> ChildHiveJobs {
-      get {
-        childHiveJobsLock.EnterReadLock();
-        try {
-          return childHiveJobs.AsReadOnly();
-        }
-        finally { childHiveJobsLock.ExitReadLock(); }
-      }
-    }
-
-    [Storable]
-    protected bool syncJobsWithOptimizers = true;
-
-    public StateLogList StateLog {
-      get { return new StateLogList(this.job.StateLog); }
-    }
-
-    public StateLogListList ChildStateLogList {
-      get { return new StateLogListList(this.childHiveJobs.Select(x => x.StateLog)); }
-    }
-
-    #region Constructors and Cloning
-    public HiveJob() {
-      this.Job = new Task() { CoresNeeded = 1, MemoryNeeded = 0 };
-      job.State = TaskState.Offline;
-      this.childHiveJobs = new ItemList<HiveJob>();
-      syncJobsWithOptimizers = true;
-      RegisterChildHiveJobEvents();
-    }
-
-    public HiveJob(ItemJob itemJob, bool autoCreateChildHiveJobs)
-      : this() {
-      this.syncJobsWithOptimizers = autoCreateChildHiveJobs;
-      this.ItemJob = itemJob;
-      this.syncJobsWithOptimizers = true;
-    }
-
-    public HiveJob(Task job, TaskData jobData, bool autoCreateChildHiveJobs) {
-      this.syncJobsWithOptimizers = autoCreateChildHiveJobs;
-      this.Job = job;
-      try {
-        this.ItemJob = PersistenceUtil.Deserialize<ItemJob>(jobData.Data);
-      }
-      catch {
-        this.ItemJob = null;
-      }
-      this.childHiveJobs = new ItemList<HiveJob>();
-      this.syncJobsWithOptimizers = true;
-      RegisterChildHiveJobEvents();
-    }
-
-    protected HiveJob(HiveJob original, Cloner cloner)
-      : base(original, cloner) {
-      this.Job = cloner.Clone(original.job);
-      this.ItemJob = cloner.Clone(original.ItemJob);
-      original.childHiveJobsLock.EnterReadLock();
-      try {
-        this.childHiveJobs = cloner.Clone(original.childHiveJobs);
-      }
-      finally { original.childHiveJobsLock.ExitReadLock(); }
-      this.syncJobsWithOptimizers = original.syncJobsWithOptimizers;
-      this.isFinishedJobDownloaded = original.isFinishedJobDownloaded;
-    }
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new HiveJob(this, cloner);
-    }
-    #endregion
-
-    protected virtual void UpdateChildHiveJobs() { }
-
-    protected virtual void RegisterItemJobEvents() {
-      if (ItemJob != null) {
-        ItemJob.ComputeInParallelChanged += new EventHandler(ItemJob_ComputeInParallelChanged);
-        ItemJob.ToStringChanged += new EventHandler(ItemJob_ToStringChanged);
-      }
-    }
-    protected virtual void DergisterItemJobEvents() {
-      if (ItemJob != null) {
-        ItemJob.ComputeInParallelChanged -= new EventHandler(ItemJob_ComputeInParallelChanged);
-        ItemJob.ToStringChanged -= new EventHandler(ItemJob_ToStringChanged);
-      }
-    }
-
-    protected virtual void RegisterChildHiveJobEvents() {
-      this.childHiveJobs.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<HiveJob>>(OnItemsAdded);
-      this.childHiveJobs.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<HiveJob>>(OnItemsRemoved);
-      this.childHiveJobs.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<HiveJob>>(OnCollectionReset);
-    }
-    protected virtual void DeregisterChildHiveJobEvents() {
-      this.childHiveJobs.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<HiveJob>>(OnItemsAdded);
-      this.childHiveJobs.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<HiveJob>>(OnItemsRemoved);
-      this.childHiveJobs.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<HiveJob>>(OnCollectionReset);
-    }
-
-    protected virtual void ItemJob_ToStringChanged(object sender, EventArgs e) {
-      this.OnToStringChanged();
-    }
-
-    protected virtual void ItemJob_ComputeInParallelChanged(object sender, EventArgs e) {
-      if (ItemJob != null && syncJobsWithOptimizers) {
-        this.UpdateChildHiveJobs();
-      }
-    }
-
-    public virtual void AddChildHiveJob(HiveJob hiveJob) {
-      childHiveJobsLock.EnterWriteLock();
-      try {
-        this.childHiveJobs.Add(hiveJob);
-      }
-      finally { childHiveJobsLock.ExitWriteLock(); }
-    }
-
-    public override string ToString() {
-      if (itemJob != null && itemJob.Item != null) {
-        return itemJob.ToString();
-      } else {
-        return Job.Id.ToString();
-      }
-    }
-
-    public virtual void UpdateFromLightweightJob(LightweightTask lightweightJob) {
-      if (lightweightJob != null) {
-        job.Id = lightweightJob.Id;
-        job.ParentTaskId = lightweightJob.ParentTaskId;
-        job.ExecutionTime = lightweightJob.ExecutionTime;
-        job.State = lightweightJob.State;
-        job.StateLog = new List<StateLog>(lightweightJob.StateLog);
-        job.Command = lightweightJob.Command;
-
-        OnJobStateChanged();
-        OnToStringChanged();
-        OnItemImageChanged();
-        OnStateLogChanged();
-      }
-    }
-
-    /// <summary>
-    /// Creates a TaskData object containing the Task and the IJob-Object as byte[]
-    /// </summary>
-    /// <param name="withoutChildOptimizers">
-    ///   if true the Child-Optimizers will not be serialized (if the job contains an Experiment)
-    /// </param>
-    public virtual TaskData GetAsJobData(bool withoutChildOptimizers, out List<IPluginDescription> plugins) {
-      plugins = new List<IPluginDescription>();
-      if (this.itemJob == null)
-        return null;
-
-      IEnumerable<Type> usedTypes;
-      byte[] jobByteArray = PersistenceUtil.Serialize(this.ItemJob, out usedTypes);
-      TaskData jobData = new TaskData() { TaskId = job.Id, Data = jobByteArray };
-      PluginUtil.CollectDeclaringPlugins(plugins, usedTypes);
-      return jobData;
-    }
-
-    #region Event Handler
-    public event EventHandler JobChanged;
-    private void OnJobChanged() {
-      EventHandler handler = JobChanged;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    public event EventHandler JobStateChanged;
-    private void OnJobStateChanged() {
-      EventHandler handler = JobStateChanged;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    public event EventHandler ItemJobChanged;
-    private void OnItemJobChanged() {
-      ItemJob_ComputeInParallelChanged(this, EventArgs.Empty);
-      var handler = ItemJobChanged;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    public event EventHandler IsFinishedJobDownloadedChanged;
-    private void OnIsFinishedJobDownloadedChanged() {
-      var handler = IsFinishedJobDownloadedChanged;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    public event EventHandler StateLogChanged;
-    private void OnStateLogChanged() {
-      var handler = StateLogChanged;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    public event EventHandler IsControllableChanged;
-    private void OnIsControllableChanged() {
-      var handler = IsControllableChanged;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    private void RegisterJobEvents() {
-      if (job != null)
-        job.PropertyChanged += new PropertyChangedEventHandler(job_PropertyChanged);
-    }
-
-    private void DeregisterJobEvents() {
-      if (job != null)
-        job.PropertyChanged += new PropertyChangedEventHandler(job_PropertyChanged);
-    }
-
-    private void job_PropertyChanged(object sender, PropertyChangedEventArgs e) {
-      if (e.PropertyName == "State") {
-        IsFinishedJobDownloaded = false;
-      }
-    }
-    #endregion
-
-    /// <summary>
-    /// Returns a list of HiveJobs including this and all its child-jobs recursively
-    /// </summary>
-    public IEnumerable<HiveJob> GetAllHiveJobs() {
-      childHiveJobsLock.EnterReadLock();
-      try {
-        var jobs = new List<HiveJob>();
-        jobs.Add(this);
-        foreach (HiveJob child in this.childHiveJobs) {
-          jobs.AddRange(child.GetAllHiveJobs());
-        }
-        return jobs;
-      }
-      finally { childHiveJobsLock.ExitReadLock(); }
-    }
-
-    public HiveJob GetParentByJobId(Guid jobId) {
-      childHiveJobsLock.EnterReadLock();
-      try {
-        if (this.ChildHiveJobs.SingleOrDefault(j => j.job.Id == jobId) != null)
-          return this;
-        foreach (HiveJob child in this.childHiveJobs) {
-          HiveJob result = child.GetParentByJobId(jobId);
-          if (result != null)
-            return result;
-        }
-        return null;
-      }
-      finally { childHiveJobsLock.ExitWriteLock(); }
-    }
-
-    /// <summary>
-    /// Searches for an HiveJob object with the correct jobId recursively
-    /// </summary>
-    public HiveJob GetHiveJobByJobId(Guid jobId) {
-      if (this.Job.Id == jobId) {
-        return this;
-      } else {
-        childHiveJobsLock.EnterReadLock();
-        try {
-          foreach (HiveJob child in this.childHiveJobs) {
-            HiveJob result = child.GetHiveJobByJobId(jobId);
-            if (result != null)
-              return result;
-          }
-        }
-        finally { childHiveJobsLock.ExitReadLock(); }
-      }
-      return null;
-    }
-
-    public void RemoveByJobId(Guid jobId) {
-      childHiveJobsLock.EnterWriteLock();
-      try {
-        IEnumerable<HiveJob> jobs = childHiveJobs.Where(j => j.Job.Id == jobId).ToList();
-        foreach (HiveJob j in jobs) {
-          this.childHiveJobs.Remove(j);
-        }
-        foreach (HiveJob child in childHiveJobs) {
-          child.RemoveByJobId(jobId);
-        }
-      }
-      finally { childHiveJobsLock.ExitWriteLock(); }
-    }
-
-    public IEnumerable<IItemTree<HiveJob>> GetChildItems() {
-      return this.ChildHiveJobs;
-    }
-
-    #region INotifyObservableCollectionItemsChanged<IItemTree> Members
-
-    public event CollectionItemsChangedEventHandler<IItemTree<HiveJob>> CollectionReset;
-    private void OnCollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<HiveJob>> e) {
-      foreach (var item in e.Items) {
-        item.Value.StateLogChanged -= new EventHandler(ChildHiveJob_StateLogChanged);
-      }
-      var handler = CollectionReset;
-      if (handler != null) handler(this, ToCollectionItemsChangedEventArgs(e));
-    }
-
-    public event CollectionItemsChangedEventHandler<IItemTree<HiveJob>> ItemsAdded;
-    private void OnItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<HiveJob>> e) {
-      foreach (var item in e.Items) {
-        item.Value.StateLogChanged += new EventHandler(ChildHiveJob_StateLogChanged);
-        item.Value.IsControllable = this.IsControllable;
-      }
-      var handler = ItemsAdded;
-      if (handler != null) handler(this, ToCollectionItemsChangedEventArgs(e));
-    }
-
-    public event CollectionItemsChangedEventHandler<IItemTree<HiveJob>> ItemsRemoved;
-    private void OnItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<HiveJob>> e) {
-      foreach (var item in e.Items) {
-        item.Value.StateLogChanged -= new EventHandler(ChildHiveJob_StateLogChanged);
-      }
-      var handler = ItemsRemoved;
-      if (handler != null) handler(this, ToCollectionItemsChangedEventArgs(e));
-    }
-
-    private static CollectionItemsChangedEventArgs<IItemTree<HiveJob>> ToCollectionItemsChangedEventArgs(CollectionItemsChangedEventArgs<IndexedItem<HiveJob>> e) {
-      return new CollectionItemsChangedEventArgs<IItemTree<HiveJob>>(e.Items.Select(x => x.Value), e.OldItems == null ? null : e.OldItems.Select(x => x.Value));
-    }
-
-    private void ChildHiveJob_StateLogChanged(object sender, EventArgs e) {
-      OnStateLogChanged();
-    }
-    #endregion
-
-    public void Pause() {
-      if (this.Job.IsParentJob) {
-        childHiveJobsLock.EnterReadLock();
-        try {
-          foreach (var child in childHiveJobs) {
-            ServiceLocator.Instance.CallHiveService(s => s.PauseJob(child.job.Id));
-          }
-        }
-        finally { childHiveJobsLock.ExitReadLock(); }
-      } else {
-        ServiceLocator.Instance.CallHiveService(s => s.PauseJob(this.job.Id));
-      }
-    }
-
-    public void Stop() {
-      if (this.Job.IsParentJob) {
-        childHiveJobsLock.EnterReadLock();
-        try {
-          foreach (var child in childHiveJobs) {
-            ServiceLocator.Instance.CallHiveService(s => s.StopJob(child.job.Id));
-          }
-        }
-        finally { childHiveJobsLock.ExitReadLock(); }
-      } else {
-        ServiceLocator.Instance.CallHiveService(s => s.StopJob(this.job.Id));
-      }
-    }
-
-    public void Restart() {
-      ServiceLocator.Instance.CallHiveService(service => {
-        TaskData jobData = new TaskData();
-        jobData.TaskId = this.job.Id;
-        jobData.Data = PersistenceUtil.Serialize(this.itemJob);
-        service.UpdateJobData(this.Job, jobData);
-        service.RestartJob(this.job.Id);
-        Task job = service.GetJob(this.job.Id);
-        this.job.LastJobDataUpdate = job.LastJobDataUpdate;
-      });
-    }
-
-    public ICollection<IItemTreeNodeAction<HiveJob>> Actions {
-      get {
-        return new List<IItemTreeNodeAction<HiveJob>>();
-      }
-    }
-
-    public virtual void IntegrateChild(ItemJob job, Guid childJobId) { }
-
-    /// <summary>
-    /// Delete ItemJob
-    /// </summary>
-    public virtual void ClearData() {
-      this.ItemJob.Item = null;
-    }
-  }
-
-  [Item("Hive Task", "Represents a hive job.")]
-  [StorableClass]
-  public class HiveJob<T> : HiveJob where T : ItemJob {
-
-    public new T ItemJob {
-      get { return (T)base.ItemJob; }
-      internal set { base.ItemJob = value; }
-    }
-
-    #region Constructors and Cloning
-    public HiveJob() : base() { }
-    public HiveJob(T itemJob) : base(itemJob, true) { }
-    protected HiveJob(HiveJob original, Cloner cloner)
-      : base(original, cloner) {
-    }
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new HiveJob<T>(this, cloner);
-    }
-    #endregion
-  }
-}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HiveJobs/HiveTask.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HiveJobs/HiveTask.cs	(revision 6725)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HiveJobs/HiveTask.cs	(revision 6725)
@@ -0,0 +1,526 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Linq;
+using System.Threading;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.Clients.Hive {
+
+  [Item("Hive Task", "Represents a hive task.")]
+  [StorableClass]
+  public class HiveTask : NamedItem, IItemTree<HiveTask> {
+    protected static object locker = new object();
+    protected ReaderWriterLockSlim childHiveTasksLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
+
+    public override Image ItemImage {
+      get {
+        if (task.Id == Guid.Empty) { // not yet uploaded
+          return HeuristicLab.Common.Resources.VSImageLibrary.Event;
+        } else {
+          if (task.State == TaskState.Waiting) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutablePrepared;
+          else if (task.State == TaskState.Calculating) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutableStarted;
+          else if (task.State == TaskState.Transferring) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutableStarted;
+          else if (task.State == TaskState.Paused) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutablePaused;
+          else if (task.State == TaskState.Aborted) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutableStopped;
+          else if (task.State == TaskState.Failed) return HeuristicLab.Common.Resources.VSImageLibrary.Error;
+          else if (task.State == TaskState.Finished) return HeuristicLab.Common.Resources.VSImageLibrary.ExecutableStopped;
+          else return HeuristicLab.Common.Resources.VSImageLibrary.Event;
+        }
+      }
+    }
+
+    [Storable]
+    protected Task task;
+    public Task Task {
+      get { return task; }
+      set {
+        if (task != value) {
+          DeregisterJobEvents();
+          task = value;
+          RegisterJobEvents();
+          IsFinishedTaskDownloaded = false;
+          OnTaskChanged();
+          OnToStringChanged();
+          OnItemImageChanged();
+        }
+
+      }
+    }
+
+    [Storable]
+    protected ItemTask itemTask;
+    public ItemTask ItemTask {
+      get { return itemTask; }
+      set {
+        if (itemTask != null && syncTasksWithOptimizers) {
+          this.childHiveTasks.Clear();
+        }
+        if (itemTask != value) {
+          DergisterItemTaskEvents();
+          itemTask = value;
+          RegisterItemTaskEvents();
+          OnItemTaskChanged();
+          IsFinishedTaskDownloaded = true;
+        }
+      }
+    }
+
+    // task downloaded since last status change
+    [Storable]
+    private bool isFinishedTaskDownloaded = false;
+    public bool IsFinishedTaskDownloaded {
+      get { return isFinishedTaskDownloaded; }
+      set {
+        if (value != isFinishedTaskDownloaded) {
+          this.isFinishedTaskDownloaded = value;
+          OnIsFinishedJobDownloadedChanged();
+        }
+      }
+    }
+
+    public bool IsDownloading { get; set; }
+
+    // if true, all control buttons should be enabled. otherwise disabled
+    private bool isControllable = true;
+    public bool IsControllable {
+      get { return isControllable; }
+      set {
+        if (value != isControllable) {
+          isControllable = value;
+          OnIsControllableChanged();
+          childHiveTasksLock.EnterReadLock();
+          try {
+            foreach (var hiveJob in childHiveTasks) {
+              hiveJob.IsControllable = value;
+            }
+          }
+          finally {
+            childHiveTasksLock.ExitReadLock();
+          }
+        }
+      }
+    }
+
+    [Storable]
+    protected ItemList<HiveTask> childHiveTasks;
+    public virtual ReadOnlyItemList<HiveTask> ChildHiveTasks {
+      get {
+        childHiveTasksLock.EnterReadLock();
+        try {
+          return childHiveTasks.AsReadOnly();
+        }
+        finally { childHiveTasksLock.ExitReadLock(); }
+      }
+    }
+
+    [Storable]
+    protected bool syncTasksWithOptimizers = true;
+
+    public StateLogList StateLog {
+      get { return new StateLogList(this.task.StateLog); }
+    }
+
+    public StateLogListList ChildStateLogList {
+      get { return new StateLogListList(this.childHiveTasks.Select(x => x.StateLog)); }
+    }
+
+    #region Constructors and Cloning
+    public HiveTask() {
+      this.Task = new Task() { CoresNeeded = 1, MemoryNeeded = 0 };
+      task.State = TaskState.Offline;
+      this.childHiveTasks = new ItemList<HiveTask>();
+      syncTasksWithOptimizers = true;
+      RegisterChildHiveJobEvents();
+    }
+
+    public HiveTask(ItemTask itemJob, bool autoCreateChildHiveJobs)
+      : this() {
+      this.syncTasksWithOptimizers = autoCreateChildHiveJobs;
+      this.ItemTask = itemJob;
+      this.syncTasksWithOptimizers = true;
+    }
+
+    public HiveTask(Task job, TaskData taskData, bool autoCreateChildHiveTasks) {
+      this.syncTasksWithOptimizers = autoCreateChildHiveTasks;
+      this.Task = job;
+      try {
+        this.ItemTask = PersistenceUtil.Deserialize<ItemTask>(taskData.Data);
+      }
+      catch {
+        this.ItemTask = null;
+      }
+      this.childHiveTasks = new ItemList<HiveTask>();
+      this.syncTasksWithOptimizers = true;
+      RegisterChildHiveJobEvents();
+    }
+
+    protected HiveTask(HiveTask original, Cloner cloner)
+      : base(original, cloner) {
+      this.Task = cloner.Clone(original.task);
+      this.ItemTask = cloner.Clone(original.ItemTask);
+      original.childHiveTasksLock.EnterReadLock();
+      try {
+        this.childHiveTasks = cloner.Clone(original.childHiveTasks);
+      }
+      finally { original.childHiveTasksLock.ExitReadLock(); }
+      this.syncTasksWithOptimizers = original.syncTasksWithOptimizers;
+      this.isFinishedTaskDownloaded = original.isFinishedTaskDownloaded;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new HiveTask(this, cloner);
+    }
+    #endregion
+
+    protected virtual void UpdateChildHiveTasks() { }
+
+    protected virtual void RegisterItemTaskEvents() {
+      if (ItemTask != null) {
+        ItemTask.ComputeInParallelChanged += new EventHandler(ItemJob_ComputeInParallelChanged);
+        ItemTask.ToStringChanged += new EventHandler(ItemJob_ToStringChanged);
+      }
+    }
+    protected virtual void DergisterItemTaskEvents() {
+      if (ItemTask != null) {
+        ItemTask.ComputeInParallelChanged -= new EventHandler(ItemJob_ComputeInParallelChanged);
+        ItemTask.ToStringChanged -= new EventHandler(ItemJob_ToStringChanged);
+      }
+    }
+
+    protected virtual void RegisterChildHiveJobEvents() {
+      this.childHiveTasks.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<HiveTask>>(OnItemsAdded);
+      this.childHiveTasks.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<HiveTask>>(OnItemsRemoved);
+      this.childHiveTasks.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<HiveTask>>(OnCollectionReset);
+    }
+    protected virtual void DeregisterChildHiveJobEvents() {
+      this.childHiveTasks.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<HiveTask>>(OnItemsAdded);
+      this.childHiveTasks.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<HiveTask>>(OnItemsRemoved);
+      this.childHiveTasks.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<HiveTask>>(OnCollectionReset);
+    }
+
+    protected virtual void ItemJob_ToStringChanged(object sender, EventArgs e) {
+      this.OnToStringChanged();
+    }
+
+    protected virtual void ItemJob_ComputeInParallelChanged(object sender, EventArgs e) {
+      if (ItemTask != null && syncTasksWithOptimizers) {
+        this.UpdateChildHiveTasks();
+      }
+    }
+
+    public virtual void AddChildHiveJob(HiveTask hiveJob) {
+      childHiveTasksLock.EnterWriteLock();
+      try {
+        this.childHiveTasks.Add(hiveJob);
+      }
+      finally { childHiveTasksLock.ExitWriteLock(); }
+    }
+
+    public override string ToString() {
+      if (itemTask != null && itemTask.Item != null) {
+        return itemTask.ToString();
+      } else {
+        return Task.Id.ToString();
+      }
+    }
+
+    public virtual void UpdateFromLightweightJob(LightweightTask lightweightJob) {
+      if (lightweightJob != null) {
+        task.Id = lightweightJob.Id;
+        task.ParentTaskId = lightweightJob.ParentTaskId;
+        task.ExecutionTime = lightweightJob.ExecutionTime;
+        task.State = lightweightJob.State;
+        task.StateLog = new List<StateLog>(lightweightJob.StateLog);
+        task.Command = lightweightJob.Command;
+
+        OnTaskStateChanged();
+        OnToStringChanged();
+        OnItemImageChanged();
+        OnStateLogChanged();
+      }
+    }
+
+    /// <summary>
+    /// Creates a TaskData object containing the Task and the IJob-Object as byte[]
+    /// </summary>
+    /// <param name="withoutChildOptimizers">
+    ///   if true the Child-Optimizers will not be serialized (if the task contains an Experiment)
+    /// </param>
+    public virtual TaskData GetAsTaskData(bool withoutChildOptimizers, out List<IPluginDescription> plugins) {
+      plugins = new List<IPluginDescription>();
+      if (this.itemTask == null)
+        return null;
+
+      IEnumerable<Type> usedTypes;
+      byte[] taskByteArray = PersistenceUtil.Serialize(this.ItemTask, out usedTypes);
+      TaskData taskData = new TaskData() { TaskId = task.Id, Data = taskByteArray };
+      PluginUtil.CollectDeclaringPlugins(plugins, usedTypes);
+      return taskData;
+    }
+
+    #region Event Handler
+    public event EventHandler JobChanged;
+    private void OnTaskChanged() {
+      EventHandler handler = JobChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler JobStateChanged;
+    private void OnTaskStateChanged() {
+      EventHandler handler = JobStateChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler ItemJobChanged;
+    private void OnItemTaskChanged() {
+      ItemJob_ComputeInParallelChanged(this, EventArgs.Empty);
+      var handler = ItemJobChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler IsFinishedJobDownloadedChanged;
+    private void OnIsFinishedJobDownloadedChanged() {
+      var handler = IsFinishedJobDownloadedChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler StateLogChanged;
+    private void OnStateLogChanged() {
+      var handler = StateLogChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler IsControllableChanged;
+    private void OnIsControllableChanged() {
+      var handler = IsControllableChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    private void RegisterJobEvents() {
+      if (task != null)
+        task.PropertyChanged += new PropertyChangedEventHandler(job_PropertyChanged);
+    }
+
+    private void DeregisterJobEvents() {
+      if (task != null)
+        task.PropertyChanged += new PropertyChangedEventHandler(job_PropertyChanged);
+    }
+
+    private void job_PropertyChanged(object sender, PropertyChangedEventArgs e) {
+      if (e.PropertyName == "State") {
+        IsFinishedTaskDownloaded = false;
+      }
+    }
+    #endregion
+
+    /// <summary>
+    /// Returns a list of HiveJobs including this and all its child-jobs recursively
+    /// </summary>
+    public IEnumerable<HiveTask> GetAllHiveTasks() {
+      childHiveTasksLock.EnterReadLock();
+      try {
+        var jobs = new List<HiveTask>();
+        jobs.Add(this);
+        foreach (HiveTask child in this.childHiveTasks) {
+          jobs.AddRange(child.GetAllHiveTasks());
+        }
+        return jobs;
+      }
+      finally { childHiveTasksLock.ExitReadLock(); }
+    }
+
+    public HiveTask GetParentByJobId(Guid taskId) {
+      childHiveTasksLock.EnterReadLock();
+      try {
+        if (this.ChildHiveTasks.SingleOrDefault(j => j.task.Id == taskId) != null)
+          return this;
+        foreach (HiveTask child in this.childHiveTasks) {
+          HiveTask result = child.GetParentByJobId(taskId);
+          if (result != null)
+            return result;
+        }
+        return null;
+      }
+      finally { childHiveTasksLock.ExitWriteLock(); }
+    }
+
+    /// <summary>
+    /// Searches for an HiveTask object with the correct taskId recursively
+    /// </summary>
+    public HiveTask GetHiveTaskByTaskId(Guid jobId) {
+      if (this.Task.Id == jobId) {
+        return this;
+      } else {
+        childHiveTasksLock.EnterReadLock();
+        try {
+          foreach (HiveTask child in this.childHiveTasks) {
+            HiveTask result = child.GetHiveTaskByTaskId(jobId);
+            if (result != null)
+              return result;
+          }
+        }
+        finally { childHiveTasksLock.ExitReadLock(); }
+      }
+      return null;
+    }
+
+    public void RemoveByTaskId(Guid jobId) {
+      childHiveTasksLock.EnterWriteLock();
+      try {
+        IEnumerable<HiveTask> jobs = childHiveTasks.Where(j => j.Task.Id == jobId).ToList();
+        foreach (HiveTask j in jobs) {
+          this.childHiveTasks.Remove(j);
+        }
+        foreach (HiveTask child in childHiveTasks) {
+          child.RemoveByTaskId(jobId);
+        }
+      }
+      finally { childHiveTasksLock.ExitWriteLock(); }
+    }
+
+    public IEnumerable<IItemTree<HiveTask>> GetChildItems() {
+      return this.ChildHiveTasks;
+    }
+
+    #region INotifyObservableCollectionItemsChanged<IItemTree> Members
+
+    public event CollectionItemsChangedEventHandler<IItemTree<HiveTask>> CollectionReset;
+    private void OnCollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<HiveTask>> e) {
+      foreach (var item in e.Items) {
+        item.Value.StateLogChanged -= new EventHandler(ChildHiveJob_StateLogChanged);
+      }
+      var handler = CollectionReset;
+      if (handler != null) handler(this, ToCollectionItemsChangedEventArgs(e));
+    }
+
+    public event CollectionItemsChangedEventHandler<IItemTree<HiveTask>> ItemsAdded;
+    private void OnItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<HiveTask>> e) {
+      foreach (var item in e.Items) {
+        item.Value.StateLogChanged += new EventHandler(ChildHiveJob_StateLogChanged);
+        item.Value.IsControllable = this.IsControllable;
+      }
+      var handler = ItemsAdded;
+      if (handler != null) handler(this, ToCollectionItemsChangedEventArgs(e));
+    }
+
+    public event CollectionItemsChangedEventHandler<IItemTree<HiveTask>> ItemsRemoved;
+    private void OnItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<HiveTask>> e) {
+      foreach (var item in e.Items) {
+        item.Value.StateLogChanged -= new EventHandler(ChildHiveJob_StateLogChanged);
+      }
+      var handler = ItemsRemoved;
+      if (handler != null) handler(this, ToCollectionItemsChangedEventArgs(e));
+    }
+
+    private static CollectionItemsChangedEventArgs<IItemTree<HiveTask>> ToCollectionItemsChangedEventArgs(CollectionItemsChangedEventArgs<IndexedItem<HiveTask>> e) {
+      return new CollectionItemsChangedEventArgs<IItemTree<HiveTask>>(e.Items.Select(x => x.Value), e.OldItems == null ? null : e.OldItems.Select(x => x.Value));
+    }
+
+    private void ChildHiveJob_StateLogChanged(object sender, EventArgs e) {
+      OnStateLogChanged();
+    }
+    #endregion
+
+    public void Pause() {
+      if (this.Task.IsParentTask) {
+        childHiveTasksLock.EnterReadLock();
+        try {
+          foreach (var child in childHiveTasks) {
+            ServiceLocator.Instance.CallHiveService(s => s.PauseJob(child.task.Id));
+          }
+        }
+        finally { childHiveTasksLock.ExitReadLock(); }
+      } else {
+        ServiceLocator.Instance.CallHiveService(s => s.PauseJob(this.task.Id));
+      }
+    }
+
+    public void Stop() {
+      if (this.Task.IsParentTask) {
+        childHiveTasksLock.EnterReadLock();
+        try {
+          foreach (var child in childHiveTasks) {
+            ServiceLocator.Instance.CallHiveService(s => s.StopJob(child.task.Id));
+          }
+        }
+        finally { childHiveTasksLock.ExitReadLock(); }
+      } else {
+        ServiceLocator.Instance.CallHiveService(s => s.StopJob(this.task.Id));
+      }
+    }
+
+    public void Restart() {
+      ServiceLocator.Instance.CallHiveService(service => {
+        TaskData taskData = new TaskData();
+        taskData.TaskId = this.task.Id;
+        taskData.Data = PersistenceUtil.Serialize(this.itemTask);
+        service.UpdateJobData(this.Task, taskData);
+        service.RestartJob(this.task.Id);
+        Task job = service.GetJob(this.task.Id);
+        this.task.LastJobDataUpdate = job.LastJobDataUpdate;
+      });
+    }
+
+    public ICollection<IItemTreeNodeAction<HiveTask>> Actions {
+      get {
+        return new List<IItemTreeNodeAction<HiveTask>>();
+      }
+    }
+
+    public virtual void IntegrateChild(ItemTask task, Guid childTaskId) { }
+
+    /// <summary>
+    /// Delete ItemTask
+    /// </summary>
+    public virtual void ClearData() {
+      this.ItemTask.Item = null;
+    }
+  }
+
+  [Item("Hive Task", "Represents a hive task.")]
+  [StorableClass]
+  public class HiveTask<T> : HiveTask where T : ItemTask {
+
+    public new T ItemTask {
+      get { return (T)base.ItemTask; }
+      internal set { base.ItemTask = value; }
+    }
+
+    #region Constructors and Cloning
+    public HiveTask() : base() { }
+    public HiveTask(T itemJob) : base(itemJob, true) { }
+    protected HiveTask(HiveTask original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new HiveTask<T>(this, cloner);
+    }
+    #endregion
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HiveJobs/OptimizerHiveJob.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HiveJobs/OptimizerHiveJob.cs	(revision 6723)
+++ 	(revision )
@@ -1,389 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using HeuristicLab.Clients.Hive.Jobs;
-using HeuristicLab.Collections;
-using HeuristicLab.Common;
-using HeuristicLab.Optimization;
-using HeuristicLab.PluginInfrastructure;
-
-namespace HeuristicLab.Clients.Hive {
-  public class OptimizerHiveJob : HiveJob<OptimizerJob> {
-
-    #region Constructors and Cloning
-    public OptimizerHiveJob() { }
-    public OptimizerHiveJob(IOptimizer optimizer)
-      : this() {
-      this.ItemJob = new OptimizerJob(optimizer);
-    }
-    public OptimizerHiveJob(OptimizerJob optimizerJob)
-      : this() {
-      this.ItemJob = optimizerJob;
-    }
-    protected OptimizerHiveJob(OptimizerHiveJob original, Cloner cloner)
-      : base(original, cloner) {
-    }
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new OptimizerHiveJob(this, cloner);
-    }
-    #endregion
-
-    /// <summary>
-    /// if this.Optimizer is an experiment
-    ///   Uses the child-optimizers of this.HiveJob and creates HiveJob-childs
-    /// if this.Optimizer is a batchrun
-    ///   Creates a number of child-jobs according to repetitions
-    /// </summary>
-    protected override void UpdateChildHiveJobs() {
-      base.UpdateChildHiveJobs();
-      if (Job != null && syncJobsWithOptimizers) {
-        if (!ItemJob.ComputeInParallel) {
-          this.childHiveJobs.Clear();
-        } else {
-          if (ItemJob.Item is Optimization.Experiment) {
-            Optimization.Experiment experiment = (Optimization.Experiment)ItemJob.Item;
-            foreach (IOptimizer childOpt in experiment.Optimizers) {
-              this.childHiveJobs.Add(new OptimizerHiveJob(childOpt));
-            }
-          } else if (ItemJob.Item is Optimization.BatchRun) {
-            Optimization.BatchRun batchRun = ItemJob.OptimizerAsBatchRun;
-            if (batchRun.Optimizer != null) {
-              while (this.childHiveJobs.Count < batchRun.Repetitions) {
-                this.childHiveJobs.Add(new OptimizerHiveJob(batchRun.Optimizer));
-              }
-              while (this.childHiveJobs.Count > batchRun.Repetitions) {
-                this.childHiveJobs.Remove(this.childHiveJobs.Last());
-              }
-            }
-          }
-        }
-      }
-    }
-
-    protected override void RegisterItemJobEvents() {
-      base.RegisterItemJobEvents();
-      if (ItemJob != null) {
-        if (ItemJob.Item is Optimization.Experiment) {
-          Optimization.Experiment experiment = ItemJob.OptimizerAsExperiment;
-          experiment.Optimizers.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsAdded);
-          experiment.Optimizers.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsReplaced);
-          experiment.Optimizers.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsRemoved);
-          experiment.Optimizers.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_CollectionReset);
-        } else if (ItemJob.Item is Optimization.BatchRun) {
-          Optimization.BatchRun batchRun = ItemJob.OptimizerAsBatchRun;
-          batchRun.RepetitionsChanged += new EventHandler(batchRun_RepetitionsChanged);
-          batchRun.OptimizerChanged += new EventHandler(batchRun_OptimizerChanged);
-        }
-      }
-    }
-    protected override void DergisterItemJobEvents() {
-      base.DergisterItemJobEvents();
-      if (ItemJob != null) {
-        if (ItemJob.Item is Optimization.Experiment) {
-          Optimization.Experiment experiment = ItemJob.OptimizerAsExperiment;
-          experiment.Optimizers.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsAdded);
-          experiment.Optimizers.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsReplaced);
-          experiment.Optimizers.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsRemoved);
-          experiment.Optimizers.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_CollectionReset);
-        } else if (ItemJob.Item is Optimization.BatchRun) {
-          Optimization.BatchRun batchRun = ItemJob.OptimizerAsBatchRun;
-          batchRun.RepetitionsChanged -= new EventHandler(batchRun_RepetitionsChanged);
-          batchRun.OptimizerChanged -= new EventHandler(batchRun_OptimizerChanged);
-        }
-      }
-    }
-
-    private void batchRun_OptimizerChanged(object sender, EventArgs e) {
-      if (syncJobsWithOptimizers) {
-        UpdateChildHiveJobs();
-      }
-    }
-
-    private void batchRun_RepetitionsChanged(object sender, EventArgs e) {
-      if (syncJobsWithOptimizers) {
-        UpdateChildHiveJobs();
-      }
-    }
-
-    private void Optimizers_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
-      if (syncJobsWithOptimizers && this.ItemJob.ComputeInParallel) {
-        childHiveJobsLock.EnterWriteLock();
-        try {
-          foreach (var item in e.Items) {
-            if (GetChildByOptimizer(item.Value) == null && item.Value.Name != "Placeholder") {
-              this.childHiveJobs.Add(new OptimizerHiveJob(item.Value));
-            }
-          }
-        }
-        finally { childHiveJobsLock.ExitWriteLock(); }
-      }
-    }
-    private void Optimizers_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
-      if (syncJobsWithOptimizers && this.ItemJob.ComputeInParallel) {
-        childHiveJobsLock.EnterWriteLock();
-        try {
-          foreach (var item in e.OldItems) {
-            this.childHiveJobs.Remove(this.GetChildByOptimizer(item.Value));
-          }
-          foreach (var item in e.Items) {
-            if (GetChildByOptimizer(item.Value) == null && item.Value.Name != "Placeholder") {
-              this.childHiveJobs.Add(new OptimizerHiveJob(item.Value));
-            }
-          }
-        }
-        finally { childHiveJobsLock.ExitWriteLock(); }
-      }
-    }
-    private void Optimizers_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
-      if (syncJobsWithOptimizers && this.ItemJob.ComputeInParallel) {
-        childHiveJobsLock.EnterWriteLock();
-        try {
-          foreach (var item in e.Items) {
-            this.childHiveJobs.Remove(this.GetChildByOptimizer(item.Value));
-          }
-        }
-        finally { childHiveJobsLock.ExitWriteLock(); }
-      }
-    }
-    private void Optimizers_CollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
-      if (syncJobsWithOptimizers && this.ItemJob.ComputeInParallel) {
-        childHiveJobsLock.EnterWriteLock();
-        try {
-          foreach (var item in e.Items) {
-            this.childHiveJobs.Remove(this.GetChildByOptimizer(item.Value));
-          }
-        }
-        finally { childHiveJobsLock.ExitWriteLock(); }
-      }
-    }
-
-    /// <summary>
-    /// if this.Optimizer is Experiment
-    ///   replace the child-optimizer in the experiment
-    /// if this.Optimizer is BatchRun
-    ///   add the runs from the optimizerJob to the batchrun and replace the Optimizer
-    /// </summary>
-    public override void IntegrateChild(ItemJob job, Guid childJobId) {
-      var optimizerJob = (OptimizerJob)job;
-      syncJobsWithOptimizers = false; // don't sync with optimizers during this method
-
-      if (this.ItemJob != null && this.ItemJob.Item != null) {
-        if (this.ItemJob.Item is Optimization.Experiment) {
-          UpdateOptimizerInExperiment(this.ItemJob.OptimizerAsExperiment, optimizerJob);
-        } else if (this.ItemJob.Item is Optimization.BatchRun) {
-          UpdateOptimizerInBatchRun(this.ItemJob.OptimizerAsBatchRun, optimizerJob);
-        }
-      }
-
-      childHiveJobsLock.EnterReadLock();
-      OptimizerHiveJob child = (OptimizerHiveJob)this.ChildHiveJobs.Single(j => j.Job.Id == childJobId);
-      try {
-        if (!optimizerJob.ComputeInParallel) {
-          child.syncJobsWithOptimizers = false;
-          child.ItemJob = optimizerJob;
-          child.syncJobsWithOptimizers = true;
-        }
-      }
-      finally { childHiveJobsLock.ExitReadLock(); }
-      syncJobsWithOptimizers = true;
-    }
-
-    /// <summary>
-    /// Adds the runs from the optimizerJob to the batchrun and replaces the Optimizer 
-    /// Sideeffect: the optimizerJob.Optimizer will be prepared (scopes are deleted and executionstate will be reset)
-    /// </summary>
-    private void UpdateOptimizerInBatchRun(BatchRun batchRun, OptimizerJob optimizerJob) {
-      if (batchRun.Optimizer == null) {
-        batchRun.Optimizer = (IOptimizer)optimizerJob.Item; // only set the first optimizer as Optimizer. if every time the Optimizer would be set, the runs would be cleared each time
-      }
-      foreach (IRun run in optimizerJob.Item.Runs) {
-        if (!batchRun.Runs.Contains(run)) {
-          run.Name = GetNewRunName(run, batchRun.Runs);
-          batchRun.Runs.Add(run);
-        }
-      }
-    }
-
-    /// <summary>
-    /// replace the child-optimizer in the experiment
-    /// Sideeffect: the optimizerJob.Optimizer will be prepared (scopes are deleted and executionstate will be reset)
-    /// </summary>
-    private void UpdateOptimizerInExperiment(Optimization.Experiment experiment, OptimizerJob optimizerJob) {
-      if (optimizerJob.IndexInParentOptimizerList < 0)
-        throw new IndexOutOfRangeException("IndexInParentOptimizerList must be equal or greater than zero! The Task is invalid and the optimizer-tree cannot be reassembled.");
-
-      while (experiment.Optimizers.Count < optimizerJob.IndexInParentOptimizerList) {
-        experiment.Optimizers.Add(new UserDefinedAlgorithm("Placeholder")); // add dummy-entries to Optimizers so that its possible to insert the optimizerJob at the correct position
-      }
-      if (experiment.Optimizers.Count < optimizerJob.IndexInParentOptimizerList + 1) {
-        experiment.Optimizers.Add(optimizerJob.Item);
-      } else {
-        // if ComputeInParallel==true, don't replace the optimizer (except it is still a Placeholder)
-        // this is because Jobs with ComputeInParallel get submitted to hive with their child-optimizers deleted
-        if (!optimizerJob.ComputeInParallel || experiment.Optimizers[optimizerJob.IndexInParentOptimizerList].Name == "Placeholder") {
-          experiment.Optimizers[optimizerJob.IndexInParentOptimizerList] = optimizerJob.Item;
-        }
-      }
-    }
-
-    /// <summary>
-    /// Sets the IndexInParentOptimizerList property of the OptimizerJob
-    /// according to the position in the OptimizerList of the parentHiveJob.Task
-    /// Recursively updates all the child-jobs as well
-    /// </summary>
-    internal void SetIndexInParentOptimizerList(OptimizerHiveJob parentHiveJob) {
-      if (parentHiveJob != null) {
-        if (parentHiveJob.ItemJob.Item is Optimization.Experiment) {
-          this.ItemJob.IndexInParentOptimizerList = parentHiveJob.ItemJob.OptimizerAsExperiment.Optimizers.IndexOf(this.ItemJob.Item);
-        } else if (parentHiveJob.ItemJob.Item is Optimization.BatchRun) {
-          this.ItemJob.IndexInParentOptimizerList = 0;
-        } else {
-          throw new NotSupportedException("Only Experiment and BatchRuns are supported");
-        }
-      }
-      childHiveJobsLock.EnterReadLock();
-      try {
-        foreach (OptimizerHiveJob child in childHiveJobs) {
-          child.SetIndexInParentOptimizerList(this);
-        }
-      }
-      finally { childHiveJobsLock.ExitReadLock(); }
-    }
-
-    public override void AddChildHiveJob(HiveJob hiveJob) {
-      base.AddChildHiveJob(hiveJob);
-      var optimizerHiveJob = (OptimizerHiveJob)hiveJob;
-      syncJobsWithOptimizers = false;
-      if (this.ItemJob != null && optimizerHiveJob.ItemJob != null) {
-        // if job is in state Paused, it has to preserve its ResultCollection, which is cleared when a optimizer is added to an experiment
-        OptimizerJob optimizerJobClone = null;
-        if (optimizerHiveJob.Job.State == TaskState.Paused) {
-          optimizerJobClone = (OptimizerJob)optimizerHiveJob.ItemJob.Clone();
-        }
-
-        if (this.ItemJob.Item is Optimization.Experiment) {
-          if (!this.ItemJob.OptimizerAsExperiment.Optimizers.Contains(optimizerHiveJob.ItemJob.Item)) {
-            UpdateOptimizerInExperiment(this.ItemJob.OptimizerAsExperiment, optimizerHiveJob.ItemJob);
-          }
-        } else if (this.ItemJob.Item is Optimization.BatchRun) {
-          UpdateOptimizerInBatchRun(this.ItemJob.OptimizerAsBatchRun, optimizerHiveJob.ItemJob);
-        }
-
-        if (optimizerHiveJob.Job.State == TaskState.Paused) {
-          optimizerHiveJob.ItemJob = optimizerJobClone;
-        }
-      }
-      syncJobsWithOptimizers = true;
-    }
-
-    /// <summary>
-    /// Creates a TaskData object containing the Task and the IJob-Object as byte[]
-    /// </summary>
-    /// <param name="withoutChildOptimizers">
-    ///   if true the Child-Optimizers will not be serialized (if the job contains an Experiment)
-    /// </param>
-    public override TaskData GetAsJobData(bool withoutChildOptimizers, out List<IPluginDescription> plugins) {
-      plugins = new List<IPluginDescription>();
-      if (this.itemJob == null) // || this.jobItem.Optimizer == null
-        return null;
-
-      IEnumerable<Type> usedTypes;
-      byte[] jobByteArray;
-      if (withoutChildOptimizers && this.ItemJob.Item is Optimization.Experiment) {
-        OptimizerJob clonedJob = (OptimizerJob)this.ItemJob.Clone(); // use a cloned job, so that the childHiveJob don't get confused
-        clonedJob.OptimizerAsExperiment.Optimizers.Clear();
-        jobByteArray = PersistenceUtil.Serialize(clonedJob, out usedTypes);
-      } else if (withoutChildOptimizers && this.ItemJob.Item is Optimization.BatchRun) {
-        OptimizerJob clonedJob = (OptimizerJob)this.ItemJob.Clone();
-        clonedJob.OptimizerAsBatchRun.Optimizer = null;
-        jobByteArray = PersistenceUtil.Serialize(clonedJob, out usedTypes);
-      } else if (this.ItemJob.Item is IAlgorithm) {
-        ((IAlgorithm)this.ItemJob.Item).StoreAlgorithmInEachRun = false; // avoid storing the algorithm in runs to reduce size
-        jobByteArray = PersistenceUtil.Serialize(this.ItemJob, out usedTypes);
-      } else {
-        jobByteArray = PersistenceUtil.Serialize(this.ItemJob, out usedTypes);
-      }
-
-      TaskData jobData = new TaskData() { TaskId = job.Id, Data = jobByteArray };
-      PluginUtil.CollectDeclaringPlugins(plugins, usedTypes);
-      return jobData;
-    }
-
-    public OptimizerHiveJob GetChildByOptimizerJob(OptimizerJob optimizerJob) {
-      childHiveJobsLock.EnterReadLock();
-      try {
-        foreach (OptimizerHiveJob child in childHiveJobs) {
-          if (child.ItemJob == optimizerJob)
-            return child;
-        }
-        return null;
-      }
-      finally { childHiveJobsLock.ExitReadLock(); }
-    }
-
-    public HiveJob<OptimizerJob> GetChildByOptimizer(IOptimizer optimizer) {
-      childHiveJobsLock.EnterReadLock();
-      try {
-        foreach (OptimizerHiveJob child in childHiveJobs) {
-          if (child.ItemJob.Item == optimizer)
-            return child;
-        }
-        return null;
-      }
-      finally { childHiveJobsLock.ExitReadLock(); }
-    }
-
-    #region Helpers
-    /// <summary>
-    /// Parses the run numbers out of runs and renames the run to the next number
-    /// </summary>
-    private static string GetNewRunName(IRun run, RunCollection runs) {
-      int idx = run.Name.IndexOf("Run ") + 4;
-
-      if (idx == -1 || runs.Count == 0)
-        return run.Name;
-
-      int maxRunNumber = int.MinValue;
-      foreach (IRun r in runs) {
-        int number = GetRunNumber(r.Name);
-        maxRunNumber = Math.Max(maxRunNumber, number);
-      }
-
-      return run.Name.Substring(0, idx) + (maxRunNumber + 1).ToString();
-    }
-
-    /// <summary>
-    /// Parses the number of a Run out of its name. Example "Genetic Algorithm Run 3" -> 3
-    /// </summary>
-    private static int GetRunNumber(string runName) {
-      int idx = runName.IndexOf("Run ") + 4;
-      if (idx == -1) {
-        return 0;
-      } else {
-        return int.Parse(runName.Substring(idx, runName.Length - idx));
-      }
-    }
-    #endregion
-  }
-}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HiveJobs/OptimizerHiveTask.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HiveJobs/OptimizerHiveTask.cs	(revision 6725)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/HiveJobs/OptimizerHiveTask.cs	(revision 6725)
@@ -0,0 +1,389 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Clients.Hive.Jobs;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Optimization;
+using HeuristicLab.PluginInfrastructure;
+
+namespace HeuristicLab.Clients.Hive {
+  public class OptimizerHiveTask : HiveTask<OptimizerTask> {
+
+    #region Constructors and Cloning
+    public OptimizerHiveTask() { }
+    public OptimizerHiveTask(IOptimizer optimizer)
+      : this() {
+      this.ItemTask = new OptimizerTask(optimizer);
+    }
+    public OptimizerHiveTask(OptimizerTask optimizerJob)
+      : this() {
+      this.ItemTask = optimizerJob;
+    }
+    protected OptimizerHiveTask(OptimizerHiveTask original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new OptimizerHiveTask(this, cloner);
+    }
+    #endregion
+
+    /// <summary>
+    /// if this.Optimizer is an experiment
+    ///   Uses the child-optimizers of this.HiveTask and creates HiveTask-childs
+    /// if this.Optimizer is a batchrun
+    ///   Creates a number of child-jobs according to repetitions
+    /// </summary>
+    protected override void UpdateChildHiveTasks() {
+      base.UpdateChildHiveTasks();
+      if (Task != null && syncTasksWithOptimizers) {
+        if (!ItemTask.ComputeInParallel) {
+          this.childHiveTasks.Clear();
+        } else {
+          if (ItemTask.Item is Optimization.Experiment) {
+            Optimization.Experiment experiment = (Optimization.Experiment)ItemTask.Item;
+            foreach (IOptimizer childOpt in experiment.Optimizers) {
+              this.childHiveTasks.Add(new OptimizerHiveTask(childOpt));
+            }
+          } else if (ItemTask.Item is Optimization.BatchRun) {
+            Optimization.BatchRun batchRun = ItemTask.OptimizerAsBatchRun;
+            if (batchRun.Optimizer != null) {
+              while (this.childHiveTasks.Count < batchRun.Repetitions) {
+                this.childHiveTasks.Add(new OptimizerHiveTask(batchRun.Optimizer));
+              }
+              while (this.childHiveTasks.Count > batchRun.Repetitions) {
+                this.childHiveTasks.Remove(this.childHiveTasks.Last());
+              }
+            }
+          }
+        }
+      }
+    }
+
+    protected override void RegisterItemTaskEvents() {
+      base.RegisterItemTaskEvents();
+      if (ItemTask != null) {
+        if (ItemTask.Item is Optimization.Experiment) {
+          Optimization.Experiment experiment = ItemTask.OptimizerAsExperiment;
+          experiment.Optimizers.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsAdded);
+          experiment.Optimizers.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsReplaced);
+          experiment.Optimizers.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsRemoved);
+          experiment.Optimizers.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_CollectionReset);
+        } else if (ItemTask.Item is Optimization.BatchRun) {
+          Optimization.BatchRun batchRun = ItemTask.OptimizerAsBatchRun;
+          batchRun.RepetitionsChanged += new EventHandler(batchRun_RepetitionsChanged);
+          batchRun.OptimizerChanged += new EventHandler(batchRun_OptimizerChanged);
+        }
+      }
+    }
+    protected override void DergisterItemTaskEvents() {
+      base.DergisterItemTaskEvents();
+      if (ItemTask != null) {
+        if (ItemTask.Item is Optimization.Experiment) {
+          Optimization.Experiment experiment = ItemTask.OptimizerAsExperiment;
+          experiment.Optimizers.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsAdded);
+          experiment.Optimizers.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsReplaced);
+          experiment.Optimizers.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsRemoved);
+          experiment.Optimizers.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_CollectionReset);
+        } else if (ItemTask.Item is Optimization.BatchRun) {
+          Optimization.BatchRun batchRun = ItemTask.OptimizerAsBatchRun;
+          batchRun.RepetitionsChanged -= new EventHandler(batchRun_RepetitionsChanged);
+          batchRun.OptimizerChanged -= new EventHandler(batchRun_OptimizerChanged);
+        }
+      }
+    }
+
+    private void batchRun_OptimizerChanged(object sender, EventArgs e) {
+      if (syncTasksWithOptimizers) {
+        UpdateChildHiveTasks();
+      }
+    }
+
+    private void batchRun_RepetitionsChanged(object sender, EventArgs e) {
+      if (syncTasksWithOptimizers) {
+        UpdateChildHiveTasks();
+      }
+    }
+
+    private void Optimizers_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
+      if (syncTasksWithOptimizers && this.ItemTask.ComputeInParallel) {
+        childHiveTasksLock.EnterWriteLock();
+        try {
+          foreach (var item in e.Items) {
+            if (GetChildByOptimizer(item.Value) == null && item.Value.Name != "Placeholder") {
+              this.childHiveTasks.Add(new OptimizerHiveTask(item.Value));
+            }
+          }
+        }
+        finally { childHiveTasksLock.ExitWriteLock(); }
+      }
+    }
+    private void Optimizers_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
+      if (syncTasksWithOptimizers && this.ItemTask.ComputeInParallel) {
+        childHiveTasksLock.EnterWriteLock();
+        try {
+          foreach (var item in e.OldItems) {
+            this.childHiveTasks.Remove(this.GetChildByOptimizer(item.Value));
+          }
+          foreach (var item in e.Items) {
+            if (GetChildByOptimizer(item.Value) == null && item.Value.Name != "Placeholder") {
+              this.childHiveTasks.Add(new OptimizerHiveTask(item.Value));
+            }
+          }
+        }
+        finally { childHiveTasksLock.ExitWriteLock(); }
+      }
+    }
+    private void Optimizers_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
+      if (syncTasksWithOptimizers && this.ItemTask.ComputeInParallel) {
+        childHiveTasksLock.EnterWriteLock();
+        try {
+          foreach (var item in e.Items) {
+            this.childHiveTasks.Remove(this.GetChildByOptimizer(item.Value));
+          }
+        }
+        finally { childHiveTasksLock.ExitWriteLock(); }
+      }
+    }
+    private void Optimizers_CollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
+      if (syncTasksWithOptimizers && this.ItemTask.ComputeInParallel) {
+        childHiveTasksLock.EnterWriteLock();
+        try {
+          foreach (var item in e.Items) {
+            this.childHiveTasks.Remove(this.GetChildByOptimizer(item.Value));
+          }
+        }
+        finally { childHiveTasksLock.ExitWriteLock(); }
+      }
+    }
+
+    /// <summary>
+    /// if this.Optimizer is Experiment
+    ///   replace the child-optimizer in the experiment
+    /// if this.Optimizer is BatchRun
+    ///   add the runs from the optimizerTask to the batchrun and replace the Optimizer
+    /// </summary>
+    public override void IntegrateChild(ItemTask task, Guid childJobId) {
+      var optimizerTask = (OptimizerTask)task;
+      syncTasksWithOptimizers = false; // don't sync with optimizers during this method
+
+      if (this.ItemTask != null && this.ItemTask.Item != null) {
+        if (this.ItemTask.Item is Optimization.Experiment) {
+          UpdateOptimizerInExperiment(this.ItemTask.OptimizerAsExperiment, optimizerTask);
+        } else if (this.ItemTask.Item is Optimization.BatchRun) {
+          UpdateOptimizerInBatchRun(this.ItemTask.OptimizerAsBatchRun, optimizerTask);
+        }
+      }
+
+      childHiveTasksLock.EnterReadLock();
+      OptimizerHiveTask child = (OptimizerHiveTask)this.ChildHiveTasks.Single(j => j.Task.Id == childJobId);
+      try {
+        if (!optimizerTask.ComputeInParallel) {
+          child.syncTasksWithOptimizers = false;
+          child.ItemTask = optimizerTask;
+          child.syncTasksWithOptimizers = true;
+        }
+      }
+      finally { childHiveTasksLock.ExitReadLock(); }
+      syncTasksWithOptimizers = true;
+    }
+
+    /// <summary>
+    /// Adds the runs from the optimizerTask to the batchrun and replaces the Optimizer 
+    /// Sideeffect: the optimizerTask.Optimizer will be prepared (scopes are deleted and executionstate will be reset)
+    /// </summary>
+    private void UpdateOptimizerInBatchRun(BatchRun batchRun, OptimizerTask optimizerTask) {
+      if (batchRun.Optimizer == null) {
+        batchRun.Optimizer = (IOptimizer)optimizerTask.Item; // only set the first optimizer as Optimizer. if every time the Optimizer would be set, the runs would be cleared each time
+      }
+      foreach (IRun run in optimizerTask.Item.Runs) {
+        if (!batchRun.Runs.Contains(run)) {
+          run.Name = GetNewRunName(run, batchRun.Runs);
+          batchRun.Runs.Add(run);
+        }
+      }
+    }
+
+    /// <summary>
+    /// replace the child-optimizer in the experiment
+    /// Sideeffect: the optimizerTask.Optimizer will be prepared (scopes are deleted and executionstate will be reset)
+    /// </summary>
+    private void UpdateOptimizerInExperiment(Optimization.Experiment experiment, OptimizerTask optimizerTask) {
+      if (optimizerTask.IndexInParentOptimizerList < 0)
+        throw new IndexOutOfRangeException("IndexInParentOptimizerList must be equal or greater than zero! The Task is invalid and the optimizer-tree cannot be reassembled.");
+
+      while (experiment.Optimizers.Count < optimizerTask.IndexInParentOptimizerList) {
+        experiment.Optimizers.Add(new UserDefinedAlgorithm("Placeholder")); // add dummy-entries to Optimizers so that its possible to insert the optimizerTask at the correct position
+      }
+      if (experiment.Optimizers.Count < optimizerTask.IndexInParentOptimizerList + 1) {
+        experiment.Optimizers.Add(optimizerTask.Item);
+      } else {
+        // if ComputeInParallel==true, don't replace the optimizer (except it is still a Placeholder)
+        // this is because Jobs with ComputeInParallel get submitted to hive with their child-optimizers deleted
+        if (!optimizerTask.ComputeInParallel || experiment.Optimizers[optimizerTask.IndexInParentOptimizerList].Name == "Placeholder") {
+          experiment.Optimizers[optimizerTask.IndexInParentOptimizerList] = optimizerTask.Item;
+        }
+      }
+    }
+
+    /// <summary>
+    /// Sets the IndexInParentOptimizerList property of the OptimizerJob
+    /// according to the position in the OptimizerList of the parentHiveTask.Task
+    /// Recursively updates all the child-jobs as well
+    /// </summary>
+    internal void SetIndexInParentOptimizerList(OptimizerHiveTask parentHiveTask) {
+      if (parentHiveTask != null) {
+        if (parentHiveTask.ItemTask.Item is Optimization.Experiment) {
+          this.ItemTask.IndexInParentOptimizerList = parentHiveTask.ItemTask.OptimizerAsExperiment.Optimizers.IndexOf(this.ItemTask.Item);
+        } else if (parentHiveTask.ItemTask.Item is Optimization.BatchRun) {
+          this.ItemTask.IndexInParentOptimizerList = 0;
+        } else {
+          throw new NotSupportedException("Only Experiment and BatchRuns are supported");
+        }
+      }
+      childHiveTasksLock.EnterReadLock();
+      try {
+        foreach (OptimizerHiveTask child in childHiveTasks) {
+          child.SetIndexInParentOptimizerList(this);
+        }
+      }
+      finally { childHiveTasksLock.ExitReadLock(); }
+    }
+
+    public override void AddChildHiveJob(HiveTask hiveJob) {
+      base.AddChildHiveJob(hiveJob);
+      var optimizerHiveJob = (OptimizerHiveTask)hiveJob;
+      syncTasksWithOptimizers = false;
+      if (this.ItemTask != null && optimizerHiveJob.ItemTask != null) {
+        // if task is in state Paused, it has to preserve its ResultCollection, which is cleared when a optimizer is added to an experiment
+        OptimizerTask optimizerJobClone = null;
+        if (optimizerHiveJob.Task.State == TaskState.Paused) {
+          optimizerJobClone = (OptimizerTask)optimizerHiveJob.ItemTask.Clone();
+        }
+
+        if (this.ItemTask.Item is Optimization.Experiment) {
+          if (!this.ItemTask.OptimizerAsExperiment.Optimizers.Contains(optimizerHiveJob.ItemTask.Item)) {
+            UpdateOptimizerInExperiment(this.ItemTask.OptimizerAsExperiment, optimizerHiveJob.ItemTask);
+          }
+        } else if (this.ItemTask.Item is Optimization.BatchRun) {
+          UpdateOptimizerInBatchRun(this.ItemTask.OptimizerAsBatchRun, optimizerHiveJob.ItemTask);
+        }
+
+        if (optimizerHiveJob.Task.State == TaskState.Paused) {
+          optimizerHiveJob.ItemTask = optimizerJobClone;
+        }
+      }
+      syncTasksWithOptimizers = true;
+    }
+
+    /// <summary>
+    /// Creates a TaskData object containing the Task and the IJob-Object as byte[]
+    /// </summary>
+    /// <param name="withoutChildOptimizers">
+    ///   if true the Child-Optimizers will not be serialized (if the task contains an Experiment)
+    /// </param>
+    public override TaskData GetAsTaskData(bool withoutChildOptimizers, out List<IPluginDescription> plugins) {
+      plugins = new List<IPluginDescription>();
+      if (this.itemTask == null) // || this.jobItem.Optimizer == null
+        return null;
+
+      IEnumerable<Type> usedTypes;
+      byte[] jobByteArray;
+      if (withoutChildOptimizers && this.ItemTask.Item is Optimization.Experiment) {
+        OptimizerTask clonedJob = (OptimizerTask)this.ItemTask.Clone(); // use a cloned task, so that the childHiveJob don't get confused
+        clonedJob.OptimizerAsExperiment.Optimizers.Clear();
+        jobByteArray = PersistenceUtil.Serialize(clonedJob, out usedTypes);
+      } else if (withoutChildOptimizers && this.ItemTask.Item is Optimization.BatchRun) {
+        OptimizerTask clonedJob = (OptimizerTask)this.ItemTask.Clone();
+        clonedJob.OptimizerAsBatchRun.Optimizer = null;
+        jobByteArray = PersistenceUtil.Serialize(clonedJob, out usedTypes);
+      } else if (this.ItemTask.Item is IAlgorithm) {
+        ((IAlgorithm)this.ItemTask.Item).StoreAlgorithmInEachRun = false; // avoid storing the algorithm in runs to reduce size
+        jobByteArray = PersistenceUtil.Serialize(this.ItemTask, out usedTypes);
+      } else {
+        jobByteArray = PersistenceUtil.Serialize(this.ItemTask, out usedTypes);
+      }
+
+      TaskData jobData = new TaskData() { TaskId = task.Id, Data = jobByteArray };
+      PluginUtil.CollectDeclaringPlugins(plugins, usedTypes);
+      return jobData;
+    }
+
+    public OptimizerHiveTask GetChildByOptimizerJob(OptimizerTask optimizerJob) {
+      childHiveTasksLock.EnterReadLock();
+      try {
+        foreach (OptimizerHiveTask child in childHiveTasks) {
+          if (child.ItemTask == optimizerJob)
+            return child;
+        }
+        return null;
+      }
+      finally { childHiveTasksLock.ExitReadLock(); }
+    }
+
+    public HiveTask<OptimizerTask> GetChildByOptimizer(IOptimizer optimizer) {
+      childHiveTasksLock.EnterReadLock();
+      try {
+        foreach (OptimizerHiveTask child in childHiveTasks) {
+          if (child.ItemTask.Item == optimizer)
+            return child;
+        }
+        return null;
+      }
+      finally { childHiveTasksLock.ExitReadLock(); }
+    }
+
+    #region Helpers
+    /// <summary>
+    /// Parses the run numbers out of runs and renames the run to the next number
+    /// </summary>
+    private static string GetNewRunName(IRun run, RunCollection runs) {
+      int idx = run.Name.IndexOf("Run ") + 4;
+
+      if (idx == -1 || runs.Count == 0)
+        return run.Name;
+
+      int maxRunNumber = int.MinValue;
+      foreach (IRun r in runs) {
+        int number = GetRunNumber(r.Name);
+        maxRunNumber = Math.Max(maxRunNumber, number);
+      }
+
+      return run.Name.Substring(0, idx) + (maxRunNumber + 1).ToString();
+    }
+
+    /// <summary>
+    /// Parses the number of a Run out of its name. Example "Genetic Algorithm Run 3" -> 3
+    /// </summary>
+    private static int GetRunNumber(string runName) {
+      int idx = runName.IndexOf("Run ") + 4;
+      if (idx == -1) {
+        return 0;
+      } else {
+        return int.Parse(runName.Substring(idx, runName.Length - idx));
+      }
+    }
+    #endregion
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/JobResultPoller.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/JobResultPoller.cs	(revision 6723)
+++ 	(revision )
@@ -1,144 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.Threading;
-using HeuristicLab.Common;
-
-namespace HeuristicLab.Clients.Hive {
-  public class JobResultPoller {
-    private bool stopRequested { get; set; }
-    private AutoResetEvent waitHandle;
-    private Thread thread;
-
-    private Guid hiveExperimentId;
-    public Guid HiveExperimentId {
-      get { return hiveExperimentId; }
-      set { hiveExperimentId = value; }
-    }
-
-    private TimeSpan interval;
-    public TimeSpan Interval {
-      get { return interval; }
-      set { interval = value; }
-    }
-
-    private bool isPolling;
-    public bool IsPolling {
-      get { return isPolling; }
-      set {
-        if (isPolling != value) {
-          isPolling = value;
-          OnIsPollingChanged();
-        }
-      }
-    }
-
-    private bool autoResumeOnException = false;
-    public bool AutoResumeOnException {
-      get { return autoResumeOnException; }
-      set { autoResumeOnException = value; }
-    }
-
-
-    public JobResultPoller(Guid hiveExperimentId, TimeSpan interval) {
-      this.isPolling = false;
-      this.hiveExperimentId = hiveExperimentId;
-      this.interval = interval;
-    }
-
-    public void Start() {
-      IsPolling = true;
-      stopRequested = false;
-      thread = new Thread(RunPolling);
-      thread.Start();
-    }
-
-    public void Stop() {
-      stopRequested = true;
-      waitHandle.Set();
-      IsPolling = false;
-      thread = null;
-    }
-
-    private void RunPolling() {
-      while (true) {
-        IsPolling = true;
-        try {
-          waitHandle = new AutoResetEvent(false);
-          while (!stopRequested) {
-            OnPollingStarted();
-            FetchJobResults();
-            OnPollingFinished();
-            waitHandle.WaitOne(Interval);
-          }
-          waitHandle.Close();
-        }
-        catch (Exception e) {
-          OnExceptionOccured(e);
-        }
-        finally {
-          IsPolling = false;
-        }
-        if (stopRequested) return;
-        if (!autoResumeOnException) return;
-      }
-    }
-
-    public IEnumerable<LightweightTask> FetchJobResults() {
-      return ServiceLocator.Instance.CallHiveService(service => {
-        var responses = new List<LightweightTask>();
-        responses.AddRange(service.GetLightweightExperimentJobs(hiveExperimentId));
-        OnJobResultsReceived(responses);
-        return responses;
-      });
-    }
-
-    public event EventHandler<EventArgs<IEnumerable<LightweightTask>>> JobResultsReceived;
-    private void OnJobResultsReceived(IEnumerable<LightweightTask> lightweightJobs) {
-      var handler = JobResultsReceived;
-      if (handler != null) handler(this, new EventArgs<IEnumerable<LightweightTask>>(lightweightJobs));
-    }
-
-    public event EventHandler<EventArgs<Exception>> ExceptionOccured;
-    private void OnExceptionOccured(Exception e) {
-      var handler = ExceptionOccured;
-      if (handler != null) handler(this, new EventArgs<Exception>(e));
-    }
-
-    public event EventHandler IsPollingChanged;
-    private void OnIsPollingChanged() {
-      var handler = IsPollingChanged;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-    public event EventHandler PollingStarted;
-    private void OnPollingStarted() {
-      var handler = PollingStarted;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-    public event EventHandler PollingFinished;
-    private void OnPollingFinished() {
-      var handler = PollingFinished;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-  }
-}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/RefreshableHiveExperiment.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/RefreshableHiveExperiment.cs	(revision 6723)
+++ 	(revision )
@@ -1,601 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Drawing;
-using System.Linq;
-using HeuristicLab.Collections;
-using HeuristicLab.Common;
-using HeuristicLab.Core;
-
-namespace HeuristicLab.Clients.Hive {
-  public class RefreshableHiveExperiment : IHiveItem, IDeepCloneable, IContent, IProgressReporter, IComparable<RefreshableHiveExperiment> {
-    private JobResultPoller jobResultPoller;
-    private ConcurrentJobDownloader<ItemJob> jobDownloader;
-    private static object locker = new object();
-
-    private Job hiveExperiment;
-    public Job HiveExperiment {
-      get { return hiveExperiment; }
-      set {
-        if (value != hiveExperiment) {
-          if (value == null)
-            throw new ArgumentNullException();
-
-          if (hiveExperiment != null) DergisterHiveExperimentEvents();
-          hiveExperiment = value;
-          if (hiveExperiment != null) {
-            RegisterHiveExperimentEvents();
-            hiveExperiment_PropertyChanged(hiveExperiment, new PropertyChangedEventArgs("Id"));
-          }
-          OnHiveExperimentChanged();
-          OnToStringChanged(this, EventArgs.Empty);
-        }
-      }
-    }
-
-    private ItemCollection<HiveJob> hiveJobs;
-    public ItemCollection<HiveJob> HiveJobs {
-      get { return hiveJobs; }
-      set {
-        if (hiveJobs != value) {
-          if (hiveJobs != null) DeregisterHiveJobsEvents();
-          hiveJobs = value;
-          if (hiveJobs != null) RegisterHiveJobsEvents();
-          OnHiveJobsChanged();
-        }
-      }
-    }
-
-    private ExecutionState executionState;
-    public ExecutionState ExecutionState {
-      get { return executionState; }
-      internal set {
-        if (executionState != value) {
-          executionState = value;
-          OnExecutionStateChanged();
-        }
-      }
-    }
-
-    private TimeSpan executionTime;
-    public TimeSpan ExecutionTime {
-      get { return executionTime; }
-      internal set {
-        if (executionTime != value) {
-          executionTime = value;
-          OnExecutionTimeChanged();
-        }
-      }
-    }
-
-    private bool refreshAutomatically;
-    public bool RefreshAutomatically {
-      get { return refreshAutomatically; }
-      set {
-        lock (locker) {
-          if (refreshAutomatically != value) {
-            refreshAutomatically = value;
-            OnRefreshAutomaticallyChanged();
-          }
-          if (RefreshAutomatically) {
-            if (this.HiveJobs != null && this.HiveJobs.Count > 0 && (jobResultPoller == null || !jobResultPoller.IsPolling)) {
-              StartResultPolling();
-            }
-          } else {
-            StopResultPolling();
-          }
-        }
-      }
-    }
-
-    // indicates if download button is enabled
-    private bool isDownloadable = true;
-    public bool IsDownloadable {
-      get { return isDownloadable; }
-      set {
-        if (value != isDownloadable) {
-          isDownloadable = value;
-          OnIsDownloadableChanged();
-        }
-      }
-    }
-
-    // if true, all control buttons should be enabled. otherwise disabled
-    private bool isControllable = true;
-    public bool IsControllable {
-      get { return isControllable; }
-      private set {
-        if (value != isControllable) {
-          isControllable = value;
-          OnIsControllableChanged();
-          if (this.hiveJobs != null) {
-            foreach (var hiveJob in this.hiveJobs) {
-              hiveJob.IsControllable = value;
-            }
-          }
-        }
-      }
-    }
-
-    // indicates if a user is allowed to share this experiment
-    private bool isSharable = true;
-    public bool IsSharable {
-      get { return isSharable; }
-      private set {
-        if (value != isSharable) {
-          isSharable = value;
-          OnIsSharableChanged();
-        }
-      }
-    }
-
-    // may execute jobs with privileged permissions on slaves
-    private bool isAllowedPrivileged = true;
-    public bool IsAllowedPrivileged {
-      get { return isAllowedPrivileged; }
-      set {
-        if (value != isAllowedPrivileged) {
-          isAllowedPrivileged = value;
-          OnIsAllowedPrivilegedChanged();
-        }
-      }
-    }
-
-    private bool isProgressing;
-    public bool IsProgressing {
-      get { return isProgressing; }
-      set {
-        if (isProgressing != value) {
-          isProgressing = value;
-          OnIsProgressingChanged();
-        }
-      }
-    }
-
-    private IProgress progress;
-    public IProgress Progress {
-      get { return progress; }
-      set { this.progress = value; }
-    }
-
-    private ThreadSafeLog log;
-    public ILog Log {
-      get { return log; }
-    }
-
-    public StateLogListList StateLogList {
-      get { return new StateLogListList(this.GetAllHiveJobs().Select(x => x.StateLog)); }
-    }
-
-    #region Constructors and Cloning
-    public RefreshableHiveExperiment() {
-      this.refreshAutomatically = true;
-      this.HiveExperiment = new Job();
-      this.log = new ThreadSafeLog(new Log());
-      this.jobDownloader = new ConcurrentJobDownloader<ItemJob>(2, 2);
-      this.jobDownloader.ExceptionOccured += new EventHandler<EventArgs<Exception>>(jobDownloader_ExceptionOccured);
-      this.HiveJobs = new ItemCollection<HiveJob>();
-    }
-    public RefreshableHiveExperiment(Job hiveExperiment) {
-      this.refreshAutomatically = true;
-      this.HiveExperiment = hiveExperiment;
-      this.log = new ThreadSafeLog(new Log());
-      this.jobDownloader = new ConcurrentJobDownloader<ItemJob>(2, 2);
-      this.jobDownloader.ExceptionOccured += new EventHandler<EventArgs<Exception>>(jobDownloader_ExceptionOccured);
-      this.HiveJobs = new ItemCollection<HiveJob>();
-    }
-    protected RefreshableHiveExperiment(RefreshableHiveExperiment original, Cloner cloner) {
-      cloner.RegisterClonedObject(original, this);
-      this.HiveExperiment = original.HiveExperiment;
-      this.IsControllable = original.IsControllable;
-      this.log = cloner.Clone(original.log);
-      this.RefreshAutomatically = false; // do not start results polling automatically
-      this.jobDownloader = new ConcurrentJobDownloader<ItemJob>(2, 2);
-      this.jobDownloader.ExceptionOccured += new EventHandler<EventArgs<Exception>>(jobDownloader_ExceptionOccured);
-      this.HiveJobs = cloner.Clone(original.HiveJobs);
-      this.ExecutionTime = original.ExecutionTime;
-      this.ExecutionState = original.ExecutionState;
-    }
-    public IDeepCloneable Clone(Cloner cloner) {
-      return new RefreshableHiveExperiment(this, cloner);
-    }
-    public object Clone() {
-      return this.Clone(new Cloner());
-    }
-    #endregion
-
-    #region JobResultPoller Events
-
-    public void StartResultPolling() {
-      if (jobResultPoller == null) {
-        jobResultPoller = new JobResultPoller(hiveExperiment.Id, /*ApplicationConstants.ResultPollingInterval*/new TimeSpan(0, 0, 5)); //TODO: find a better place for ApplicationConstants
-        RegisterResultPollingEvents();
-        jobResultPoller.AutoResumeOnException = true;
-      }
-
-      if (!jobResultPoller.IsPolling) {
-        jobResultPoller.Start();
-      }
-    }
-
-    public void StopResultPolling() {
-      if (jobResultPoller != null && jobResultPoller.IsPolling) {
-        jobResultPoller.Stop();
-      }
-    }
-
-    private void RegisterResultPollingEvents() {
-      jobResultPoller.ExceptionOccured += new EventHandler<EventArgs<Exception>>(jobResultPoller_ExceptionOccured);
-      jobResultPoller.JobResultsReceived += new EventHandler<EventArgs<IEnumerable<LightweightTask>>>(jobResultPoller_JobResultReceived);
-      jobResultPoller.IsPollingChanged += new EventHandler(jobResultPoller_IsPollingChanged);
-    }
-    private void DeregisterResultPollingEvents() {
-      jobResultPoller.ExceptionOccured -= new EventHandler<EventArgs<Exception>>(jobResultPoller_ExceptionOccured);
-      jobResultPoller.JobResultsReceived -= new EventHandler<EventArgs<IEnumerable<LightweightTask>>>(jobResultPoller_JobResultReceived);
-      jobResultPoller.IsPollingChanged -= new EventHandler(jobResultPoller_IsPollingChanged);
-    }
-    private void jobResultPoller_IsPollingChanged(object sender, EventArgs e) {
-      if (this.refreshAutomatically != jobResultPoller.IsPolling) {
-        this.refreshAutomatically = jobResultPoller.IsPolling;
-        OnRefreshAutomaticallyChanged();
-      }
-    }
-    private void jobResultPoller_JobResultReceived(object sender, EventArgs<IEnumerable<LightweightTask>> e) {
-      foreach (LightweightTask lightweightJob in e.Value) {
-        HiveJob hiveJob = GetHiveJobById(lightweightJob.Id);
-        if (hiveJob != null) {
-          // lastJobDataUpdate equals DateTime.MinValue right after it was uploaded. When the first results are polled, this value is updated
-          if (hiveJob.Job.State == TaskState.Offline && lightweightJob.State != TaskState.Finished && lightweightJob.State != TaskState.Failed && lightweightJob.State != TaskState.Aborted) {
-            hiveJob.Job.LastJobDataUpdate = lightweightJob.LastJobDataUpdate;
-          }
-
-          hiveJob.UpdateFromLightweightJob(lightweightJob);
-
-          if (!hiveJob.IsFinishedJobDownloaded && !hiveJob.IsDownloading && hiveJob.Job.LastJobDataUpdate < lightweightJob.LastJobDataUpdate) {
-            log.LogMessage(string.Format("Downloading job {0}", lightweightJob.Id));
-            hiveJob.IsDownloading = true;
-            jobDownloader.DownloadJob(hiveJob.Job, (localJob, itemJob) => {
-              log.LogMessage(string.Format("Finished downloading job {0}", localJob.Id));
-              HiveJob localHiveJob = GetHiveJobById(localJob.Id);
-
-              if (itemJob == null) {
-                localHiveJob.IsDownloading = false;
-              }
-
-              if (itemJob == null) {
-                // something bad happened to this job. bad job, BAAAD job!
-              } else {
-                // if the job is paused, download but don't integrate into parent optimizer (to avoid Prepare)
-
-                if (localJob.State == TaskState.Paused) {
-                  localHiveJob.ItemJob = itemJob;
-                } else {
-                  if (localJob.ParentTaskId.HasValue) {
-                    HiveJob parentHiveJob = GetHiveJobById(localJob.ParentTaskId.Value);
-                    parentHiveJob.IntegrateChild(itemJob, localJob.Id);
-                  } else {
-                    localHiveJob.ItemJob = itemJob;
-                  }
-                }
-                localHiveJob.IsDownloading = false;
-                localHiveJob.Job.LastJobDataUpdate = localJob.LastJobDataUpdate;
-              }
-            });
-          }
-        }
-      }
-      GC.Collect(); // force GC, because .NET is too lazy here (deserialization takes a lot of memory)
-      if (AllJobsFinished()) {
-        this.ExecutionState = Core.ExecutionState.Stopped;
-        StopResultPolling();
-      }
-      UpdateTotalExecutionTime();
-      UpdateStatistics();
-      OnStateLogListChanged();
-    }
-
-    public HiveJob GetHiveJobById(Guid jobId) {
-      foreach (HiveJob job in this.HiveJobs) {
-        var hj = job.GetHiveJobByJobId(jobId);
-        if (hj != null)
-          return hj;
-      }
-      return null;
-    }
-    private void UpdateStatistics() {
-      var jobs = this.GetAllHiveJobs();
-      hiveExperiment.JobCount = jobs.Count();
-      hiveExperiment.CalculatingCount = jobs.Count(j => j.Job.State == TaskState.Calculating);
-      hiveExperiment.FinishedCount = jobs.Count(j => j.Job.State == TaskState.Finished);
-      OnJobStatisticsChanged();
-    }
-
-    public bool AllJobsFinished() {
-      return this.GetAllHiveJobs().All(j => (j.Job.State == TaskState.Finished
-                                                   || j.Job.State == TaskState.Aborted
-                                                   || j.Job.State == TaskState.Failed)
-                                                   && j.IsFinishedJobDownloaded);
-    }
-
-    private void jobResultPoller_ExceptionOccured(object sender, EventArgs<Exception> e) {
-      OnExceptionOccured(e.Value);
-    }
-    private void jobDownloader_ExceptionOccured(object sender, EventArgs<Exception> e) {
-      OnExceptionOccured(e.Value);
-    }
-    public void UpdateTotalExecutionTime() {
-      this.ExecutionTime = TimeSpan.FromMilliseconds(this.GetAllHiveJobs().Sum(x => x.Job.ExecutionTime.TotalMilliseconds));
-    }
-    #endregion
-
-    #region Job Events
-    private void RegisterHiveExperimentEvents() {
-      hiveExperiment.ToStringChanged += new EventHandler(OnToStringChanged);
-      hiveExperiment.PropertyChanged += new PropertyChangedEventHandler(hiveExperiment_PropertyChanged);
-      hiveExperiment.ItemImageChanged += new EventHandler(hiveExperiment_ItemImageChanged);
-      hiveExperiment.ModifiedChanged += new EventHandler(hiveExperiment_ModifiedChanged);
-    }
-
-    private void DergisterHiveExperimentEvents() {
-      hiveExperiment.ToStringChanged -= new EventHandler(OnToStringChanged);
-      hiveExperiment.PropertyChanged -= new PropertyChangedEventHandler(hiveExperiment_PropertyChanged);
-      hiveExperiment.ItemImageChanged -= new EventHandler(hiveExperiment_ItemImageChanged);
-      hiveExperiment.ModifiedChanged -= new EventHandler(hiveExperiment_ModifiedChanged);
-    }
-    #endregion
-
-    #region Event Handler
-    public event EventHandler RefreshAutomaticallyChanged;
-    private void OnRefreshAutomaticallyChanged() {
-      var handler = RefreshAutomaticallyChanged;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    public event EventHandler HiveExperimentChanged;
-    private void OnHiveExperimentChanged() {
-      var handler = HiveExperimentChanged;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    public event EventHandler ModifiedChanged;
-    private void hiveExperiment_ModifiedChanged(object sender, EventArgs e) {
-      var handler = ModifiedChanged;
-      if (handler != null) handler(sender, e);
-    }
-
-    public event EventHandler ItemImageChanged;
-    private void hiveExperiment_ItemImageChanged(object sender, EventArgs e) {
-      var handler = ItemImageChanged;
-      if (handler != null) handler(this, e);
-    }
-
-    public event PropertyChangedEventHandler PropertyChanged;
-    private void hiveExperiment_PropertyChanged(object sender, PropertyChangedEventArgs e) {
-      this.IsSharable = hiveExperiment.Permission == Permission.Full;
-      this.IsControllable = hiveExperiment.Permission == Permission.Full;
-
-      var handler = PropertyChanged;
-      if (handler != null) handler(sender, e);
-    }
-
-    public event EventHandler ToStringChanged;
-    private void OnToStringChanged(object sender, EventArgs e) {
-      var handler = ToStringChanged;
-      if (handler != null) handler(this, e);
-    }
-
-    public event EventHandler IsProgressingChanged;
-    protected virtual void OnIsProgressingChanged() {
-      var handler = IsProgressingChanged;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    public event EventHandler IsDownloadableChanged;
-    private void OnIsDownloadableChanged() {
-      var handler = IsDownloadableChanged;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    public event EventHandler IsControllableChanged;
-    private void OnIsControllableChanged() {
-      var handler = IsControllableChanged;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    public event EventHandler IsSharableChanged;
-    private void OnIsSharableChanged() {
-      var handler = IsSharableChanged;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    public event EventHandler IsAllowedPrivilegedChanged;
-    private void OnIsAllowedPrivilegedChanged() {
-      var handler = IsAllowedPrivilegedChanged;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    public event EventHandler JobStatisticsChanged;
-    private void OnJobStatisticsChanged() {
-      var handler = JobStatisticsChanged;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    public event EventHandler<EventArgs<Exception>> ExceptionOccured;
-    private void OnExceptionOccured(Exception exception) {
-      log.LogException(exception);
-      var handler = ExceptionOccured;
-      if (handler != null) handler(this, new EventArgs<Exception>(exception));
-    }
-
-    public event EventHandler StateLogListChanged;
-    private void OnStateLogListChanged() {
-      var handler = StateLogListChanged;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    public event EventHandler ExecutionTimeChanged;
-    protected virtual void OnExecutionTimeChanged() {
-      var handler = ExecutionTimeChanged;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    public event EventHandler ExecutionStateChanged;
-    protected virtual void OnExecutionStateChanged() {
-      var handler = ExecutionStateChanged;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-    #endregion
-
-    #region HiveJobs Events
-    private void RegisterHiveJobsEvents() {
-      this.hiveJobs.ItemsAdded += new CollectionItemsChangedEventHandler<HiveJob>(hiveJobs_ItemsAdded);
-      this.hiveJobs.ItemsRemoved += new CollectionItemsChangedEventHandler<HiveJob>(hiveJobs_ItemsRemoved);
-      this.hiveJobs.CollectionReset += new CollectionItemsChangedEventHandler<HiveJob>(hiveJobs_CollectionReset);
-    }
-
-    private void DeregisterHiveJobsEvents() {
-      this.hiveJobs.ItemsAdded -= new CollectionItemsChangedEventHandler<HiveJob>(hiveJobs_ItemsAdded);
-      this.hiveJobs.ItemsRemoved -= new CollectionItemsChangedEventHandler<HiveJob>(hiveJobs_ItemsRemoved);
-      this.hiveJobs.CollectionReset -= new CollectionItemsChangedEventHandler<HiveJob>(hiveJobs_CollectionReset);
-    }
-
-    private void hiveJobs_CollectionReset(object sender, CollectionItemsChangedEventArgs<HiveJob> e) {
-      foreach (var item in e.Items) {
-        item.StateLogChanged -= new EventHandler(item_StateLogChanged);
-      }
-      OnHiveJobsReset(e);
-    }
-
-    private void hiveJobs_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<HiveJob> e) {
-      foreach (var item in e.Items) {
-        item.StateLogChanged -= new EventHandler(item_StateLogChanged);
-      }
-      OnHiveJobsRemoved(e);
-    }
-
-    private void hiveJobs_ItemsAdded(object sender, CollectionItemsChangedEventArgs<HiveJob> e) {
-      foreach (var item in e.Items) {
-        item.StateLogChanged += new EventHandler(item_StateLogChanged);
-        item.IsControllable = this.IsControllable;
-      }
-      OnHiveJobsAdded(e);
-    }
-
-    private void item_StateLogChanged(object sender, EventArgs e) {
-      OnStateLogListChanged();
-    }
-    #endregion
-
-    public event EventHandler HiveJobsChanged;
-    protected virtual void OnHiveJobsChanged() {
-      if (jobResultPoller != null && jobResultPoller.IsPolling) {
-        jobResultPoller.Stop();
-        DeregisterResultPollingEvents();
-      }
-      if (this.HiveJobs != null && this.HiveJobs.Count > 0 && this.GetAllHiveJobs().All(x => x.Job.Id != Guid.Empty)) {
-        if (this.RefreshAutomatically)
-          StartResultPolling();
-      }
-
-      var handler = HiveJobsChanged;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    public event EventHandler Loaded;
-    public virtual void OnLoaded() {
-      this.UpdateTotalExecutionTime();
-
-      if (this.ExecutionState != ExecutionState.Stopped) {
-        this.RefreshAutomatically = true;
-      }
-
-      var handler = Loaded;
-      if (handler != null) handler(this, EventArgs.Empty);
-    }
-
-    public event EventHandler<CollectionItemsChangedEventArgs<HiveJob>> HiveJobsAdded;
-    private void OnHiveJobsAdded(CollectionItemsChangedEventArgs<HiveJob> e) {
-      var handler = HiveJobsAdded;
-      if (handler != null) handler(this, e);
-    }
-
-    public event EventHandler<CollectionItemsChangedEventArgs<HiveJob>> HiveJobsRemoved;
-    private void OnHiveJobsRemoved(CollectionItemsChangedEventArgs<HiveJob> e) {
-      var handler = HiveJobsRemoved;
-      if (handler != null) handler(this, e);
-    }
-
-    public event EventHandler<CollectionItemsChangedEventArgs<HiveJob>> HiveJobsReset;
-    private void OnHiveJobsReset(CollectionItemsChangedEventArgs<HiveJob> e) {
-      var handler = HiveJobsReset;
-      if (handler != null) handler(this, e);
-    }
-
-    public Guid Id {
-      get { return hiveExperiment.Id; }
-      set { hiveExperiment.Id = value; }
-    }
-    public bool Modified {
-      get { return hiveExperiment.Modified; }
-    }
-    public void Store() {
-      hiveExperiment.Store();
-    }
-    public string ItemDescription {
-      get { return hiveExperiment.ItemDescription; }
-    }
-    public Image ItemImage {
-      get { return hiveExperiment.ItemImage; }
-    }
-    public string ItemName {
-      get { return hiveExperiment.ItemName; }
-    }
-    public Version ItemVersion {
-      get { return hiveExperiment.ItemVersion; }
-    }
-
-    public override string ToString() {
-      return string.Format("{0} {1}", HiveExperiment.DateCreated.ToString("MM.dd.yyyy HH:mm"), HiveExperiment.ToString());
-    }
-
-    public bool IsFinished() {
-      return HiveJobs != null
-        && HiveJobs.All(x => x.Job.DateFinished.HasValue && x.Job.DateCreated.HasValue);
-    }
-
-    public IEnumerable<HiveJob> GetAllHiveJobs() {
-      if (hiveJobs == null) return Enumerable.Empty<HiveJob>();
-
-      var jobs = new List<HiveJob>();
-      foreach (HiveJob job in HiveJobs) {
-        jobs.AddRange(job.GetAllHiveJobs());
-      }
-      return jobs;
-    }
-
-    public int CompareTo(RefreshableHiveExperiment other) {
-      return this.ToString().CompareTo(other.ToString());
-    }
-  }
-}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/RefreshableJob.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/RefreshableJob.cs	(revision 6725)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/RefreshableJob.cs	(revision 6725)
@@ -0,0 +1,601 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Linq;
+using HeuristicLab.Collections;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Clients.Hive {
+  public class RefreshableJob : IHiveItem, IDeepCloneable, IContent, IProgressReporter, IComparable<RefreshableJob> {
+    private JobResultPoller jobResultPoller;
+    private ConcurrentTaskDownloader<ItemTask> jobDownloader;
+    private static object locker = new object();
+
+    private Job job;
+    public Job Job {
+      get { return job; }
+      set {
+        if (value != job) {
+          if (value == null)
+            throw new ArgumentNullException();
+
+          if (job != null) DergisterJobEvents();
+          job = value;
+          if (job != null) {
+            RegisterJobEvents();
+            job_PropertyChanged(job, new PropertyChangedEventArgs("Id"));
+          }
+          OnJobChanged();
+          OnToStringChanged(this, EventArgs.Empty);
+        }
+      }
+    }
+
+    private ItemCollection<HiveTask> hiveJobs;
+    public ItemCollection<HiveTask> HiveJobs {
+      get { return hiveJobs; }
+      set {
+        if (hiveJobs != value) {
+          if (hiveJobs != null) DeregisterHiveJobsEvents();
+          hiveJobs = value;
+          if (hiveJobs != null) RegisterHiveJobsEvents();
+          OnHiveJobsChanged();
+        }
+      }
+    }
+
+    private ExecutionState executionState;
+    public ExecutionState ExecutionState {
+      get { return executionState; }
+      internal set {
+        if (executionState != value) {
+          executionState = value;
+          OnExecutionStateChanged();
+        }
+      }
+    }
+
+    private TimeSpan executionTime;
+    public TimeSpan ExecutionTime {
+      get { return executionTime; }
+      internal set {
+        if (executionTime != value) {
+          executionTime = value;
+          OnExecutionTimeChanged();
+        }
+      }
+    }
+
+    private bool refreshAutomatically;
+    public bool RefreshAutomatically {
+      get { return refreshAutomatically; }
+      set {
+        lock (locker) {
+          if (refreshAutomatically != value) {
+            refreshAutomatically = value;
+            OnRefreshAutomaticallyChanged();
+          }
+          if (RefreshAutomatically) {
+            if (this.HiveJobs != null && this.HiveJobs.Count > 0 && (jobResultPoller == null || !jobResultPoller.IsPolling)) {
+              StartResultPolling();
+            }
+          } else {
+            StopResultPolling();
+          }
+        }
+      }
+    }
+
+    // indicates if download button is enabled
+    private bool isDownloadable = true;
+    public bool IsDownloadable {
+      get { return isDownloadable; }
+      set {
+        if (value != isDownloadable) {
+          isDownloadable = value;
+          OnIsDownloadableChanged();
+        }
+      }
+    }
+
+    // if true, all control buttons should be enabled. otherwise disabled
+    private bool isControllable = true;
+    public bool IsControllable {
+      get { return isControllable; }
+      private set {
+        if (value != isControllable) {
+          isControllable = value;
+          OnIsControllableChanged();
+          if (this.hiveJobs != null) {
+            foreach (var hiveJob in this.hiveJobs) {
+              hiveJob.IsControllable = value;
+            }
+          }
+        }
+      }
+    }
+
+    // indicates if a user is allowed to share this experiment
+    private bool isSharable = true;
+    public bool IsSharable {
+      get { return isSharable; }
+      private set {
+        if (value != isSharable) {
+          isSharable = value;
+          OnIsSharableChanged();
+        }
+      }
+    }
+
+    // may execute jobs with privileged permissions on slaves
+    private bool isAllowedPrivileged = true;
+    public bool IsAllowedPrivileged {
+      get { return isAllowedPrivileged; }
+      set {
+        if (value != isAllowedPrivileged) {
+          isAllowedPrivileged = value;
+          OnIsAllowedPrivilegedChanged();
+        }
+      }
+    }
+
+    private bool isProgressing;
+    public bool IsProgressing {
+      get { return isProgressing; }
+      set {
+        if (isProgressing != value) {
+          isProgressing = value;
+          OnIsProgressingChanged();
+        }
+      }
+    }
+
+    private IProgress progress;
+    public IProgress Progress {
+      get { return progress; }
+      set { this.progress = value; }
+    }
+
+    private ThreadSafeLog log;
+    public ILog Log {
+      get { return log; }
+    }
+
+    public StateLogListList StateLogList {
+      get { return new StateLogListList(this.GetAllHiveJobs().Select(x => x.StateLog)); }
+    }
+
+    #region Constructors and Cloning
+    public RefreshableJob() {
+      this.refreshAutomatically = true;
+      this.Job = new Job();
+      this.log = new ThreadSafeLog(new Log());
+      this.jobDownloader = new ConcurrentTaskDownloader<ItemTask>(2, 2);
+      this.jobDownloader.ExceptionOccured += new EventHandler<EventArgs<Exception>>(jobDownloader_ExceptionOccured);
+      this.HiveJobs = new ItemCollection<HiveTask>();
+    }
+    public RefreshableJob(Job hiveExperiment) {
+      this.refreshAutomatically = true;
+      this.Job = hiveExperiment;
+      this.log = new ThreadSafeLog(new Log());
+      this.jobDownloader = new ConcurrentTaskDownloader<ItemTask>(2, 2);
+      this.jobDownloader.ExceptionOccured += new EventHandler<EventArgs<Exception>>(jobDownloader_ExceptionOccured);
+      this.HiveJobs = new ItemCollection<HiveTask>();
+    }
+    protected RefreshableJob(RefreshableJob original, Cloner cloner) {
+      cloner.RegisterClonedObject(original, this);
+      this.Job = original.Job;
+      this.IsControllable = original.IsControllable;
+      this.log = cloner.Clone(original.log);
+      this.RefreshAutomatically = false; // do not start results polling automatically
+      this.jobDownloader = new ConcurrentTaskDownloader<ItemTask>(2, 2);
+      this.jobDownloader.ExceptionOccured += new EventHandler<EventArgs<Exception>>(jobDownloader_ExceptionOccured);
+      this.HiveJobs = cloner.Clone(original.HiveJobs);
+      this.ExecutionTime = original.ExecutionTime;
+      this.ExecutionState = original.ExecutionState;
+    }
+    public IDeepCloneable Clone(Cloner cloner) {
+      return new RefreshableJob(this, cloner);
+    }
+    public object Clone() {
+      return this.Clone(new Cloner());
+    }
+    #endregion
+
+    #region JobResultPoller Events
+
+    public void StartResultPolling() {
+      if (jobResultPoller == null) {
+        jobResultPoller = new JobResultPoller(job.Id, /*ApplicationConstants.ResultPollingInterval*/new TimeSpan(0, 0, 5)); //TODO: find a better place for ApplicationConstants
+        RegisterResultPollingEvents();
+        jobResultPoller.AutoResumeOnException = true;
+      }
+
+      if (!jobResultPoller.IsPolling) {
+        jobResultPoller.Start();
+      }
+    }
+
+    public void StopResultPolling() {
+      if (jobResultPoller != null && jobResultPoller.IsPolling) {
+        jobResultPoller.Stop();
+      }
+    }
+
+    private void RegisterResultPollingEvents() {
+      jobResultPoller.ExceptionOccured += new EventHandler<EventArgs<Exception>>(jobResultPoller_ExceptionOccured);
+      jobResultPoller.JobResultsReceived += new EventHandler<EventArgs<IEnumerable<LightweightTask>>>(jobResultPoller_JobResultReceived);
+      jobResultPoller.IsPollingChanged += new EventHandler(jobResultPoller_IsPollingChanged);
+    }
+    private void DeregisterResultPollingEvents() {
+      jobResultPoller.ExceptionOccured -= new EventHandler<EventArgs<Exception>>(jobResultPoller_ExceptionOccured);
+      jobResultPoller.JobResultsReceived -= new EventHandler<EventArgs<IEnumerable<LightweightTask>>>(jobResultPoller_JobResultReceived);
+      jobResultPoller.IsPollingChanged -= new EventHandler(jobResultPoller_IsPollingChanged);
+    }
+    private void jobResultPoller_IsPollingChanged(object sender, EventArgs e) {
+      if (this.refreshAutomatically != jobResultPoller.IsPolling) {
+        this.refreshAutomatically = jobResultPoller.IsPolling;
+        OnRefreshAutomaticallyChanged();
+      }
+    }
+    private void jobResultPoller_JobResultReceived(object sender, EventArgs<IEnumerable<LightweightTask>> e) {
+      foreach (LightweightTask lightweightJob in e.Value) {
+        HiveTask hiveJob = GetHiveJobById(lightweightJob.Id);
+        if (hiveJob != null) {
+          // lastJobDataUpdate equals DateTime.MinValue right after it was uploaded. When the first results are polled, this value is updated
+          if (hiveJob.Task.State == TaskState.Offline && lightweightJob.State != TaskState.Finished && lightweightJob.State != TaskState.Failed && lightweightJob.State != TaskState.Aborted) {
+            hiveJob.Task.LastJobDataUpdate = lightweightJob.LastJobDataUpdate;
+          }
+
+          hiveJob.UpdateFromLightweightJob(lightweightJob);
+
+          if (!hiveJob.IsFinishedTaskDownloaded && !hiveJob.IsDownloading && hiveJob.Task.LastJobDataUpdate < lightweightJob.LastJobDataUpdate) {
+            log.LogMessage(string.Format("Downloading task {0}", lightweightJob.Id));
+            hiveJob.IsDownloading = true;
+            jobDownloader.DownloadJob(hiveJob.Task, (localJob, itemJob) => {
+              log.LogMessage(string.Format("Finished downloading task {0}", localJob.Id));
+              HiveTask localHiveJob = GetHiveJobById(localJob.Id);
+
+              if (itemJob == null) {
+                localHiveJob.IsDownloading = false;
+              }
+
+              if (itemJob == null) {
+                // something bad happened to this task. bad task, BAAAD task!
+              } else {
+                // if the task is paused, download but don't integrate into parent optimizer (to avoid Prepare)
+
+                if (localJob.State == TaskState.Paused) {
+                  localHiveJob.ItemTask = itemJob;
+                } else {
+                  if (localJob.ParentTaskId.HasValue) {
+                    HiveTask parentHiveJob = GetHiveJobById(localJob.ParentTaskId.Value);
+                    parentHiveJob.IntegrateChild(itemJob, localJob.Id);
+                  } else {
+                    localHiveJob.ItemTask = itemJob;
+                  }
+                }
+                localHiveJob.IsDownloading = false;
+                localHiveJob.Task.LastJobDataUpdate = localJob.LastJobDataUpdate;
+              }
+            });
+          }
+        }
+      }
+      GC.Collect(); // force GC, because .NET is too lazy here (deserialization takes a lot of memory)
+      if (AllJobsFinished()) {
+        this.ExecutionState = Core.ExecutionState.Stopped;
+        StopResultPolling();
+      }
+      UpdateTotalExecutionTime();
+      UpdateStatistics();
+      OnStateLogListChanged();
+    }
+
+    public HiveTask GetHiveJobById(Guid jobId) {
+      foreach (HiveTask job in this.HiveJobs) {
+        var hj = job.GetHiveTaskByTaskId(jobId);
+        if (hj != null)
+          return hj;
+      }
+      return null;
+    }
+    private void UpdateStatistics() {
+      var jobs = this.GetAllHiveJobs();
+      job.JobCount = jobs.Count();
+      job.CalculatingCount = jobs.Count(j => j.Task.State == TaskState.Calculating);
+      job.FinishedCount = jobs.Count(j => j.Task.State == TaskState.Finished);
+      OnJobStatisticsChanged();
+    }
+
+    public bool AllJobsFinished() {
+      return this.GetAllHiveJobs().All(j => (j.Task.State == TaskState.Finished
+                                                   || j.Task.State == TaskState.Aborted
+                                                   || j.Task.State == TaskState.Failed)
+                                                   && j.IsFinishedTaskDownloaded);
+    }
+
+    private void jobResultPoller_ExceptionOccured(object sender, EventArgs<Exception> e) {
+      OnExceptionOccured(e.Value);
+    }
+    private void jobDownloader_ExceptionOccured(object sender, EventArgs<Exception> e) {
+      OnExceptionOccured(e.Value);
+    }
+    public void UpdateTotalExecutionTime() {
+      this.ExecutionTime = TimeSpan.FromMilliseconds(this.GetAllHiveJobs().Sum(x => x.Task.ExecutionTime.TotalMilliseconds));
+    }
+    #endregion
+
+    #region Task Events
+    private void RegisterJobEvents() {
+      job.ToStringChanged += new EventHandler(OnToStringChanged);
+      job.PropertyChanged += new PropertyChangedEventHandler(job_PropertyChanged);
+      job.ItemImageChanged += new EventHandler(job_ItemImageChanged);
+      job.ModifiedChanged += new EventHandler(job_ModifiedChanged);
+    }
+
+    private void DergisterJobEvents() {
+      job.ToStringChanged -= new EventHandler(OnToStringChanged);
+      job.PropertyChanged -= new PropertyChangedEventHandler(job_PropertyChanged);
+      job.ItemImageChanged -= new EventHandler(job_ItemImageChanged);
+      job.ModifiedChanged -= new EventHandler(job_ModifiedChanged);
+    }
+    #endregion
+
+    #region Event Handler
+    public event EventHandler RefreshAutomaticallyChanged;
+    private void OnRefreshAutomaticallyChanged() {
+      var handler = RefreshAutomaticallyChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler JobChanged;
+    private void OnJobChanged() {
+      var handler = JobChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler ModifiedChanged;
+    private void job_ModifiedChanged(object sender, EventArgs e) {
+      var handler = ModifiedChanged;
+      if (handler != null) handler(sender, e);
+    }
+
+    public event EventHandler ItemImageChanged;
+    private void job_ItemImageChanged(object sender, EventArgs e) {
+      var handler = ItemImageChanged;
+      if (handler != null) handler(this, e);
+    }
+
+    public event PropertyChangedEventHandler PropertyChanged;
+    private void job_PropertyChanged(object sender, PropertyChangedEventArgs e) {
+      this.IsSharable = job.Permission == Permission.Full;
+      this.IsControllable = job.Permission == Permission.Full;
+
+      var handler = PropertyChanged;
+      if (handler != null) handler(sender, e);
+    }
+
+    public event EventHandler ToStringChanged;
+    private void OnToStringChanged(object sender, EventArgs e) {
+      var handler = ToStringChanged;
+      if (handler != null) handler(this, e);
+    }
+
+    public event EventHandler IsProgressingChanged;
+    protected virtual void OnIsProgressingChanged() {
+      var handler = IsProgressingChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler IsDownloadableChanged;
+    private void OnIsDownloadableChanged() {
+      var handler = IsDownloadableChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler IsControllableChanged;
+    private void OnIsControllableChanged() {
+      var handler = IsControllableChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler IsSharableChanged;
+    private void OnIsSharableChanged() {
+      var handler = IsSharableChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler IsAllowedPrivilegedChanged;
+    private void OnIsAllowedPrivilegedChanged() {
+      var handler = IsAllowedPrivilegedChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler JobStatisticsChanged;
+    private void OnJobStatisticsChanged() {
+      var handler = JobStatisticsChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler<EventArgs<Exception>> ExceptionOccured;
+    private void OnExceptionOccured(Exception exception) {
+      log.LogException(exception);
+      var handler = ExceptionOccured;
+      if (handler != null) handler(this, new EventArgs<Exception>(exception));
+    }
+
+    public event EventHandler StateLogListChanged;
+    private void OnStateLogListChanged() {
+      var handler = StateLogListChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler ExecutionTimeChanged;
+    protected virtual void OnExecutionTimeChanged() {
+      var handler = ExecutionTimeChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler ExecutionStateChanged;
+    protected virtual void OnExecutionStateChanged() {
+      var handler = ExecutionStateChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    #endregion
+
+    #region HiveJobs Events
+    private void RegisterHiveJobsEvents() {
+      this.hiveJobs.ItemsAdded += new CollectionItemsChangedEventHandler<HiveTask>(hiveJobs_ItemsAdded);
+      this.hiveJobs.ItemsRemoved += new CollectionItemsChangedEventHandler<HiveTask>(hiveJobs_ItemsRemoved);
+      this.hiveJobs.CollectionReset += new CollectionItemsChangedEventHandler<HiveTask>(hiveJobs_CollectionReset);
+    }
+
+    private void DeregisterHiveJobsEvents() {
+      this.hiveJobs.ItemsAdded -= new CollectionItemsChangedEventHandler<HiveTask>(hiveJobs_ItemsAdded);
+      this.hiveJobs.ItemsRemoved -= new CollectionItemsChangedEventHandler<HiveTask>(hiveJobs_ItemsRemoved);
+      this.hiveJobs.CollectionReset -= new CollectionItemsChangedEventHandler<HiveTask>(hiveJobs_CollectionReset);
+    }
+
+    private void hiveJobs_CollectionReset(object sender, CollectionItemsChangedEventArgs<HiveTask> e) {
+      foreach (var item in e.Items) {
+        item.StateLogChanged -= new EventHandler(item_StateLogChanged);
+      }
+      OnHiveJobsReset(e);
+    }
+
+    private void hiveJobs_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<HiveTask> e) {
+      foreach (var item in e.Items) {
+        item.StateLogChanged -= new EventHandler(item_StateLogChanged);
+      }
+      OnHiveJobsRemoved(e);
+    }
+
+    private void hiveJobs_ItemsAdded(object sender, CollectionItemsChangedEventArgs<HiveTask> e) {
+      foreach (var item in e.Items) {
+        item.StateLogChanged += new EventHandler(item_StateLogChanged);
+        item.IsControllable = this.IsControllable;
+      }
+      OnHiveJobsAdded(e);
+    }
+
+    private void item_StateLogChanged(object sender, EventArgs e) {
+      OnStateLogListChanged();
+    }
+    #endregion
+
+    public event EventHandler HiveJobsChanged;
+    protected virtual void OnHiveJobsChanged() {
+      if (jobResultPoller != null && jobResultPoller.IsPolling) {
+        jobResultPoller.Stop();
+        DeregisterResultPollingEvents();
+      }
+      if (this.HiveJobs != null && this.HiveJobs.Count > 0 && this.GetAllHiveJobs().All(x => x.Task.Id != Guid.Empty)) {
+        if (this.RefreshAutomatically)
+          StartResultPolling();
+      }
+
+      var handler = HiveJobsChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler Loaded;
+    public virtual void OnLoaded() {
+      this.UpdateTotalExecutionTime();
+
+      if (this.ExecutionState != ExecutionState.Stopped) {
+        this.RefreshAutomatically = true;
+      }
+
+      var handler = Loaded;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler<CollectionItemsChangedEventArgs<HiveTask>> HiveJobsAdded;
+    private void OnHiveJobsAdded(CollectionItemsChangedEventArgs<HiveTask> e) {
+      var handler = HiveJobsAdded;
+      if (handler != null) handler(this, e);
+    }
+
+    public event EventHandler<CollectionItemsChangedEventArgs<HiveTask>> HiveJobsRemoved;
+    private void OnHiveJobsRemoved(CollectionItemsChangedEventArgs<HiveTask> e) {
+      var handler = HiveJobsRemoved;
+      if (handler != null) handler(this, e);
+    }
+
+    public event EventHandler<CollectionItemsChangedEventArgs<HiveTask>> HiveJobsReset;
+    private void OnHiveJobsReset(CollectionItemsChangedEventArgs<HiveTask> e) {
+      var handler = HiveJobsReset;
+      if (handler != null) handler(this, e);
+    }
+
+    public Guid Id {
+      get { return job.Id; }
+      set { job.Id = value; }
+    }
+    public bool Modified {
+      get { return job.Modified; }
+    }
+    public void Store() {
+      job.Store();
+    }
+    public string ItemDescription {
+      get { return job.ItemDescription; }
+    }
+    public Image ItemImage {
+      get { return job.ItemImage; }
+    }
+    public string ItemName {
+      get { return job.ItemName; }
+    }
+    public Version ItemVersion {
+      get { return job.ItemVersion; }
+    }
+
+    public override string ToString() {
+      return string.Format("{0} {1}", Job.DateCreated.ToString("MM.dd.yyyy HH:mm"), Job.ToString());
+    }
+
+    public bool IsFinished() {
+      return HiveJobs != null
+        && HiveJobs.All(x => x.Task.DateFinished.HasValue && x.Task.DateCreated.HasValue);
+    }
+
+    public IEnumerable<HiveTask> GetAllHiveJobs() {
+      if (hiveJobs == null) return Enumerable.Empty<HiveTask>();
+
+      var jobs = new List<HiveTask>();
+      foreach (HiveTask job in HiveJobs) {
+        jobs.AddRange(job.GetAllHiveTasks());
+      }
+      return jobs;
+    }
+
+    public int CompareTo(RefreshableJob other) {
+      return this.ToString().CompareTo(other.ToString());
+    }
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/ServiceClients/HiveServiceClient.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/ServiceClients/HiveServiceClient.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/ServiceClients/HiveServiceClient.cs	(revision 6725)
@@ -59,4 +59,6 @@
 
     public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
+
+
   }
 
@@ -281,5 +283,5 @@
 
     [System.Runtime.Serialization.OptionalFieldAttribute()]
-    private bool IsParentJobField;
+    private bool IsParentTaskField;
 
     [System.Runtime.Serialization.OptionalFieldAttribute()]
@@ -328,12 +330,12 @@
 
     [System.Runtime.Serialization.DataMemberAttribute()]
-    public bool IsParentJob {
-      get {
-        return this.IsParentJobField;
-      }
-      set {
-        if ((this.IsParentJobField.Equals(value) != true)) {
-          this.IsParentJobField = value;
-          this.RaisePropertyChanged("IsParentJob");
+    public bool IsParentTask {
+      get {
+        return this.IsParentTaskField;
+      }
+      set {
+        if ((this.IsParentTaskField.Equals(value) != true)) {
+          this.IsParentTaskField = value;
+          this.RaisePropertyChanged("IsParentTask");
         }
       }
@@ -1475,8 +1477,8 @@
 
       [System.Runtime.Serialization.EnumMemberAttribute()]
-      CalculateJob = 0,
+      CalculateTask = 0,
 
       [System.Runtime.Serialization.EnumMemberAttribute()]
-      StopJob = 1,
+      StopTask = 1,
 
       [System.Runtime.Serialization.EnumMemberAttribute()]
@@ -1484,5 +1486,5 @@
 
       [System.Runtime.Serialization.EnumMemberAttribute()]
-      AbortJob = 3,
+      AbortTask = 3,
 
       [System.Runtime.Serialization.EnumMemberAttribute()]
@@ -1490,5 +1492,5 @@
 
       [System.Runtime.Serialization.EnumMemberAttribute()]
-      PauseJob = 5,
+      PauseTask = 5,
 
       [System.Runtime.Serialization.EnumMemberAttribute()]
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/ServiceClients/Task.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/ServiceClients/Task.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/ServiceClients/Task.cs	(revision 6725)
@@ -36,5 +36,5 @@
       this.PluginsNeededIds = new List<Guid>(original.PluginsNeededIds);
       this.LastHeartbeat = original.LastHeartbeat;
-      this.IsParentJob = original.IsParentJob;
+      this.IsParentTask = original.IsParentTask;
       this.FinishWhenChildJobsFinished = original.FinishWhenChildJobsFinished;
       this.JobId = original.JobId;
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/TaskDownloader.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/TaskDownloader.cs	(revision 6725)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/TaskDownloader.cs	(revision 6725)
@@ -0,0 +1,105 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Clients.Hive.Jobs;
+using HeuristicLab.Common;
+
+namespace HeuristicLab.Clients.Hive {
+  public class TaskDownloader {
+    private IEnumerable<Guid> taskIds;
+    private ConcurrentTaskDownloader<ItemTask> taskDownloader;
+    private IDictionary<Guid, HiveTask> results;
+    private bool exceptionOccured = false;
+    private Exception currentException;
+
+    public bool IsFinished {
+      get {
+        return results.Count == taskIds.Count();
+      }
+    }
+
+    public bool IsFaulted {
+      get {
+        return exceptionOccured;
+      }
+    }
+
+    public Exception Exception {
+      get {
+        return currentException;
+      }
+    }
+    
+    public int FinishedCount {
+      get {
+        return results.Count;
+      }
+    }
+
+    public IDictionary<Guid, HiveTask> Results {
+      get {
+        return results;
+      }
+    }
+
+    public TaskDownloader(IEnumerable<Guid> jobIds) {
+      this.taskIds = jobIds;
+      this.taskDownloader = new ConcurrentTaskDownloader<ItemTask>(2, 2);
+      this.taskDownloader.ExceptionOccured += new EventHandler<EventArgs<Exception>>(taskDownloader_ExceptionOccured);
+      this.results = new Dictionary<Guid, HiveTask>();
+    }
+    
+    public void StartAsync() {
+      foreach (Guid jobId in taskIds) {
+        Task job = ServiceLocator.Instance.CallHiveService(s => s.GetJob(jobId));
+
+        taskDownloader.DownloadJob(job,
+          (localJob, itemJob) => {
+            if (localJob != null && itemJob != null) {
+              HiveTask hiveJob;
+              if (itemJob is OptimizerTask) {
+                hiveJob = new OptimizerHiveTask((OptimizerTask)itemJob);
+              } else {
+                hiveJob = new HiveTask(itemJob, true);
+              }
+              hiveJob.Task = localJob;
+              this.results.Add(localJob.Id, hiveJob);
+            }
+          });
+      }      
+    }
+
+    private void taskDownloader_ExceptionOccured(object sender, EventArgs<Exception> e) {
+      OnExceptionOccured(e.Value);
+    }
+
+    public event EventHandler<EventArgs<Exception>> ExceptionOccured;
+    private void OnExceptionOccured(Exception exception) {
+      this.exceptionOccured = true;
+      this.currentException = exception;
+      var handler = ExceptionOccured;
+      if (handler != null) handler(this, new EventArgs<Exception>(exception));
+    }
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/Tasks/EngineTask.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/Tasks/EngineTask.cs	(revision 6725)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/Tasks/EngineTask.cs	(revision 6725)
@@ -0,0 +1,145 @@
+﻿using System;
+using System.Drawing;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Clients.Hive {
+  [StorableClass]
+  public class EngineTask : ItemTask {
+    [Storable]
+    protected IOperation initialOperation;
+    public IOperation InitialOperation {
+      get { return initialOperation; }
+      set { initialOperation = value; }
+    }
+
+    public new IEngine Item {
+      get { return (IEngine)base.Item; }
+      set { base.Item = value; }
+    }
+
+    public override TimeSpan ExecutionTime {
+      get { return Item.ExecutionTime; }
+    }
+
+    public override ExecutionState ExecutionState {
+      get { return Item.ExecutionState; }
+    }
+
+    #region constructors and cloning
+    public EngineTask() { }
+    public EngineTask(IOperation initialOperation, IEngine engine) {
+      this.initialOperation = initialOperation;
+      this.Item = engine;
+    }
+
+    [StorableConstructor]
+    protected EngineTask(bool deserializing) : base(deserializing) { }
+    protected EngineTask(EngineTask original, Cloner cloner)
+      : base(original, cloner) {
+      this.initialOperation = cloner.Clone(original.initialOperation);
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new EngineTask(this, cloner);
+    }
+    #endregion
+
+    public override bool IsParallelizable {
+      get { return false; }
+    }
+
+    public override void Prepare() { }
+
+    public override void Start() {
+      Item.Prepare(initialOperation);
+      Item.Start();
+    }
+
+    public override void Pause() {
+      Item.Pause();
+    }
+
+    public override void Stop() {
+      Item.Stop();
+    }
+
+    protected override void RegisterItemEvents() {
+      base.RegisterItemEvents();
+      Item.Stopped += new EventHandler(engine_Stopped);
+      Item.Paused += new EventHandler(Item_Paused);
+      Item.Started += new EventHandler(Item_Started);
+      Item.ExceptionOccurred += new EventHandler<EventArgs<Exception>>(engine_ExceptionOccurred);
+      Item.ExecutionStateChanged += new EventHandler(Item_ExecutionStateChanged);
+      Item.ExecutionTimeChanged += new EventHandler(Item_ExecutionTimeChanged);
+    }
+
+    protected override void DeregisterItemEvents() {
+      Item.Stopped -= new EventHandler(engine_Stopped);
+      Item.Paused -= new EventHandler(Item_Paused);
+      Item.Started -= new EventHandler(Item_Started);
+      Item.ExceptionOccurred -= new EventHandler<EventArgs<Exception>>(engine_ExceptionOccurred);
+      Item.ExecutionStateChanged -= new EventHandler(Item_ExecutionStateChanged);
+      Item.ExecutionTimeChanged -= new EventHandler(Item_ExecutionTimeChanged);
+      base.DeregisterItemEvents();
+    }
+
+    private void engine_ExceptionOccurred(object sender, EventArgs<Exception> e) {
+      OnTaskFailed(e);
+    }
+
+    private void engine_Stopped(object sender, EventArgs e) {
+      OnTaskStopped();
+    }
+
+    private void Item_Paused(object sender, EventArgs e) {
+      OnTaskPaused();
+    }
+
+    private void Item_ExecutionTimeChanged(object sender, EventArgs e) {
+      OnExecutionTimeChanged();
+    }
+
+    private void Item_ExecutionStateChanged(object sender, EventArgs e) {
+      OnExecutionStateChanged();
+    }
+
+    private void Item_Started(object sender, EventArgs e) {
+      OnTaskStarted();
+    }
+
+    public override bool CanChangeDescription {
+      get { return false; }
+    }
+
+    public override bool CanChangeName {
+      get { return false; }
+    }
+
+    public override string Description {
+      get { return string.Empty; }
+      set { throw new NotSupportedException(); }
+    }
+
+    public override string Name {
+      get { return Item != null ? Item.ToString() : null; }
+      set { throw new NotSupportedException(); }
+    }
+
+    public override string ItemDescription {
+      get { return Description; }
+    }
+
+    public override Image ItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Operator; }
+    }
+
+    public override string ItemName {
+      get { return "EngineTask"; }
+    }
+
+    public override Version ItemVersion {
+      get { return null; }
+    }
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/Tasks/ItemTask.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/Tasks/ItemTask.cs	(revision 6725)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/Tasks/ItemTask.cs	(revision 6725)
@@ -0,0 +1,221 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Drawing;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Hive;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Clients.Hive {
+  [Item("Item Task", "Represents a executable hive task which contains a HeuristicLab Item.")]
+  [StorableClass]
+  public abstract class ItemTask : NamedItem, ITask {
+    public virtual bool IsParallelizable {
+      get { return true; }
+    }
+
+    [Storable]
+    protected IItem item;
+    public IItem Item {
+      get { return item; }
+      set {
+        if (value != item) {
+          if (item != null) DeregisterItemEvents();
+          item = value;
+          if (item != null) RegisterItemEvents();
+          OnItemChanged();
+        }
+      }
+    }
+
+    [Storable]
+    protected bool computeInParallel;
+    public bool ComputeInParallel {
+      get { return computeInParallel; }
+      set {
+        if (computeInParallel != value) {
+          computeInParallel = value;
+          OnComputeInParallelChanged();
+        }
+      }
+    }
+
+    #region Constructors and Cloning
+    public ItemTask() { }
+
+    [StorableConstructor]
+    protected ItemTask(bool deserializing) { }
+    protected ItemTask(ItemTask original, Cloner cloner)
+      : base(original, cloner) {
+      this.ComputeInParallel = original.ComputeInParallel;
+      this.Item = cloner.Clone(original.Item);
+    }
+
+    [StorableHook(HookType.AfterDeserialization)]
+    protected virtual void AfterDeserialization() {
+      RegisterItemEvents();
+    }
+    #endregion
+
+    #region Item Events
+    protected virtual void RegisterItemEvents() {
+      item.ItemImageChanged += new EventHandler(item_ItemImageChanged);
+      item.ToStringChanged += new EventHandler(item_ToStringChanged);
+    }
+
+    protected virtual void DeregisterItemEvents() {
+      item.ItemImageChanged -= new EventHandler(item_ItemImageChanged);
+      item.ToStringChanged -= new EventHandler(item_ToStringChanged);
+    }
+
+    protected void item_ToStringChanged(object sender, EventArgs e) {
+      this.OnToStringChanged();
+    }
+    protected void item_ItemImageChanged(object sender, EventArgs e) {
+      this.OnItemImageChanged();
+    }
+
+    #endregion
+
+    #region ITask Members
+
+    public abstract ExecutionState ExecutionState { get; }
+
+    public abstract TimeSpan ExecutionTime { get; }
+
+    public abstract void Prepare();
+
+    public abstract void Start();
+
+    public abstract void Pause();
+
+    public abstract void Stop();
+
+    public event EventHandler TaskStarted;
+    protected virtual void OnTaskStarted() {
+      EventHandler handler = TaskStarted;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler TaskStopped;
+    protected virtual void OnTaskStopped() {
+      EventHandler handler = TaskStopped;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler TaskPaused;
+    protected virtual void OnTaskPaused() {
+      EventHandler handler = TaskPaused;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler TaskFailed;
+    protected virtual void OnTaskFailed(EventArgs<Exception> e) {
+      EventHandler handler = TaskFailed;
+      if (handler != null) handler(this, e);
+    }
+
+    public event EventHandler ComputeInParallelChanged;
+    protected virtual void OnComputeInParallelChanged() {
+      EventHandler handler = ComputeInParallelChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+
+    public event EventHandler ItemChanged;
+    protected virtual void OnItemChanged() {
+      EventHandler handler = ItemChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    #endregion
+
+    #region INamedItem Members
+    public abstract bool CanChangeDescription { get; }
+
+    public abstract bool CanChangeName { get; }
+
+    public abstract string Description { get; set; }
+
+    public abstract string Name { get; set; }
+    #endregion
+
+    #region Events
+    public event EventHandler DescriptionChanged;
+    protected virtual void OnDescriptionChanged() {
+      var handler = DescriptionChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler ItemImageChanged;
+    protected virtual void OnItemImageChanged() {
+      var handler = ItemImageChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler ToStringChanged;
+    protected virtual void OnToStringChanged() {
+      var handler = ToStringChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler NameChanged;
+    protected virtual void OnNameChanged() {
+      var handler = NameChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler<CancelEventArgs<string>> NameChanging;
+    protected virtual void OnNameChanging(string value, bool cancel) {
+      var handler = NameChanging;
+      if (handler != null) handler(this, new CancelEventArgs<string>(value, cancel));
+    }
+    public event EventHandler ExecutionTimeChanged;
+    protected virtual void OnExecutionTimeChanged() {
+      EventHandler handler = ExecutionTimeChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    public event EventHandler ExecutionStateChanged;
+    protected virtual void OnExecutionStateChanged() {
+      EventHandler handler = ExecutionStateChanged;
+      if (handler != null) handler(this, EventArgs.Empty);
+    }
+    #endregion
+
+    #region IItem Members
+    public virtual string ItemDescription {
+      get { return item.ItemDescription; }
+    }
+
+    public virtual Image ItemImage {
+      get { return item.ItemImage; }
+    }
+
+    public virtual string ItemName {
+      get { return item.ItemName; }
+    }
+
+    public virtual Version ItemVersion {
+      get { return item.ItemVersion; }
+    }
+    #endregion
+
+    public override string ToString() {
+      return Name;
+    }
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/Tasks/OptimizerTask.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/Tasks/OptimizerTask.cs	(revision 6725)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/Tasks/OptimizerTask.cs	(revision 6725)
@@ -0,0 +1,200 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Optimization;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Clients.Hive.Jobs {
+  [Item("Optimizer Task", "Represents Task which executes a IOptimizer object.")]
+  [StorableClass]
+  public class OptimizerTask : ItemTask {
+    public override bool IsParallelizable {
+      get { return this.Item is Experiment || this.Item is BatchRun; }
+    }
+
+    public new IOptimizer Item {
+      get { return (IOptimizer)base.Item; }
+      set { base.Item = value; }
+    }
+
+    [Storable]
+    private int indexInParentOptimizerList = -1;
+    public int IndexInParentOptimizerList {
+      get { return indexInParentOptimizerList; }
+      set { this.indexInParentOptimizerList = value; }
+    }
+
+    public OptimizerTask() : base() { }
+    public OptimizerTask(IOptimizer optimizer)
+      : this() {
+      this.Item = optimizer;
+
+      if (optimizer is Experiment) {
+        this.ComputeInParallel = true;
+      } else if (optimizer is BatchRun) {
+        this.ComputeInParallel = false;
+      } else {
+        this.ComputeInParallel = false;
+      }
+    }
+    [StorableConstructor]
+    protected OptimizerTask(bool deserializing) { }
+    protected OptimizerTask(OptimizerTask original, Cloner cloner)
+      : base(original, cloner) {
+      this.IndexInParentOptimizerList = original.IndexInParentOptimizerList;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new OptimizerTask(this, cloner);
+    }
+
+    /// <summary>
+    /// Casts the Optimizer to an Experiment. Returns null if cast was not successfull.
+    /// </summary>
+    public Experiment OptimizerAsExperiment {
+      get { return Item as Experiment; }
+    }
+
+    /// <summary>
+    /// Casts the Optimizer to an BatchRun. Returns null if cast was not successfull.
+    /// </summary>
+    public BatchRun OptimizerAsBatchRun {
+      get { return Item as BatchRun; }
+    }
+
+    #region ITask Members
+    public override ExecutionState ExecutionState {
+      get { return Item.ExecutionState; }
+    }
+
+    public override TimeSpan ExecutionTime {
+      get { return Item.ExecutionTime; }
+    }
+
+    public override void Prepare() {
+      Item.Prepare();
+    }
+
+    public override void Start() {
+      if ((Item is Experiment && OptimizerAsExperiment.Optimizers.Count == 0) || // experiment would not fire OnStopped if it has 0 optimizers
+          (Item is BatchRun && OptimizerAsBatchRun.Optimizer == null)) { // batchrun would not fire OnStopped if algorithm == null
+        OnTaskStopped();
+      } else {
+        Item.Start();
+      }
+    }
+
+    public override void Pause() {
+      Item.Pause();
+    }
+
+    public override void Stop() {
+      Item.Stop();
+    }
+    #endregion
+
+    #region Optimizer Events
+    protected override void RegisterItemEvents() {
+      base.RegisterItemEvents();
+      Item.Stopped += new EventHandler(optimizer_Stopped);
+      Item.Paused += new EventHandler(optimizer_Paused);
+      Item.ExceptionOccurred += new EventHandler<EventArgs<Exception>>(optimizer_ExceptionOccurred);
+      Item.DescriptionChanged += new EventHandler(optimizer_DescriptionChanged);
+      Item.NameChanged += new EventHandler(optimizer_NameChanged);
+      Item.NameChanging += new EventHandler<CancelEventArgs<string>>(optimizer_NameChanging);
+      Item.ExecutionStateChanged += new EventHandler(optimizer_ExecutionStateChanged);
+      Item.ExecutionTimeChanged += new EventHandler(optimizer_ExecutionTimeChanged);
+      Item.Started += new EventHandler(optimizer_Started);
+    }
+
+    protected virtual void DeregisterOptimizerEvents() {
+      Item.Stopped -= new EventHandler(optimizer_Stopped);
+      Item.Paused -= new EventHandler(optimizer_Paused);
+      Item.ExceptionOccurred -= new EventHandler<EventArgs<Exception>>(optimizer_ExceptionOccurred);
+      Item.DescriptionChanged -= new EventHandler(optimizer_DescriptionChanged);
+      Item.NameChanged -= new EventHandler(optimizer_NameChanged);
+      Item.NameChanging -= new EventHandler<CancelEventArgs<string>>(optimizer_NameChanging);
+      Item.ExecutionStateChanged -= new EventHandler(optimizer_ExecutionStateChanged);
+      Item.ExecutionTimeChanged -= new EventHandler(optimizer_ExecutionTimeChanged);
+      Item.Started -= new EventHandler(optimizer_Started);
+      base.DeregisterItemEvents();
+    }
+
+    protected void optimizer_NameChanging(object sender, CancelEventArgs<string> e) {
+      this.OnNameChanging(e.Value, e.Cancel);
+    }
+
+    protected void optimizer_NameChanged(object sender, EventArgs e) {
+      this.OnNameChanged();
+    }
+
+    protected void optimizer_DescriptionChanged(object sender, EventArgs e) {
+      this.OnDescriptionChanged();
+    }
+
+    protected virtual void optimizer_ExceptionOccurred(object sender, EventArgs<Exception> e) {
+      OnTaskFailed(e);
+    }
+
+    protected virtual void optimizer_Started(object sender, EventArgs e) {
+      OnTaskStarted();
+    }
+
+    protected virtual void optimizer_Stopped(object sender, EventArgs e) {
+      OnTaskStopped();
+    }
+
+    protected virtual void optimizer_Paused(object sender, EventArgs e) {
+      OnTaskPaused();
+    }
+
+    protected virtual void optimizer_ExecutionTimeChanged(object sender, EventArgs e) {
+      OnExecutionTimeChanged();
+    }
+
+    protected virtual void optimizer_ExecutionStateChanged(object sender, EventArgs e) {
+      OnExecutionStateChanged();
+    }
+    #endregion
+
+    #region INamedItem Members
+    public override bool CanChangeDescription {
+      get { return Item.CanChangeDescription; }
+    }
+
+    public override bool CanChangeName {
+      get { return Item.CanChangeName; }
+    }
+
+    public override string Description {
+      get { return Item.Description; }
+      set { Item.Description = value; }
+    }
+
+    public override string Name {
+      get { return Item.Name; }
+      set { Item.Name = value; }
+    }
+    #endregion
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/Util/PluginUtil.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/Util/PluginUtil.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.3/Util/PluginUtil.cs	(revision 6725)
@@ -36,5 +36,5 @@
     /// <param name="service">An active service-proxy</param>
     /// <param name="onlinePlugins">List of plugins which are available online</param>
-    /// <param name="alreadyUploadedPlugins">List of plugins which have been uploaded from this Job</param>
+    /// <param name="alreadyUploadedPlugins">List of plugins which have been uploaded from this Task</param>
     /// <param name="neededPlugins">List of plugins which need to be uploaded</param>
     /// <returns></returns>
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Hive/3.3/HeuristicLab.Hive-3.3.csproj
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Hive/3.3/HeuristicLab.Hive-3.3.csproj	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Hive/3.3/HeuristicLab.Hive-3.3.csproj	(revision 6725)
@@ -95,5 +95,5 @@
     <None Include="HeuristicLabHivePlugin.cs.frame" />
     <Compile Include="HeuristicLabHivePlugin.cs" />
-    <Compile Include="IJob.cs" />
+    <Compile Include="ITask.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
   </ItemGroup>
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Hive/3.3/IJob.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Hive/3.3/IJob.cs	(revision 6723)
+++ 	(revision )
@@ -1,66 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-using HeuristicLab.Common;
-using HeuristicLab.Core;
-
-namespace HeuristicLab.Hive {
-  public interface IJob : IDeepCloneable, ICloneable {
-    TimeSpan ExecutionTime { get; }
-
-    ExecutionState ExecutionState { get; }
-
-    /// <summary>
-    /// indicates wether it is possible to create childjobs from this job
-    /// </summary>
-    bool IsParallelizable { get; }
-
-    /// <summary>
-    /// Configuration to indicate if this job should create child-jobs which will be executed in hive
-    /// Cannot be set true if IsParallelizable is false
-    /// </summary>
-    bool ComputeInParallel { get; set; }
-
-
-    void Prepare();
-
-    void Start();
-
-    void Pause();
-
-    void Stop();
-
-    event EventHandler ComputeInParallelChanged;
-
-    event EventHandler ExecutionTimeChanged;
-
-    event EventHandler ExecutionStateChanged;
-
-    event EventHandler JobFailed;
-
-    event EventHandler JobStopped;
-
-    event EventHandler JobPaused;
-
-    event EventHandler JobStarted;
-  }
-}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Hive/3.3/ITask.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Hive/3.3/ITask.cs	(revision 6725)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Hive/3.3/ITask.cs	(revision 6725)
@@ -0,0 +1,66 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.Hive {
+  public interface ITask : IDeepCloneable, ICloneable {
+    TimeSpan ExecutionTime { get; }
+
+    ExecutionState ExecutionState { get; }
+
+    /// <summary>
+    /// indicates wether it is possible to create childjobs from this job
+    /// </summary>
+    bool IsParallelizable { get; }
+
+    /// <summary>
+    /// Configuration to indicate if this job should create child-jobs which will be executed in hive
+    /// Cannot be set true if IsParallelizable is false
+    /// </summary>
+    bool ComputeInParallel { get; set; }
+
+
+    void Prepare();
+
+    void Start();
+
+    void Pause();
+
+    void Stop();
+
+    event EventHandler ComputeInParallelChanged;
+
+    event EventHandler ExecutionTimeChanged;
+
+    event EventHandler ExecutionStateChanged;
+
+    event EventHandler TaskFailed;
+
+    event EventHandler TaskStopped;
+
+    event EventHandler TaskPaused;
+
+    event EventHandler TaskStarted;
+  }
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.HiveEngine.Views/3.3/HiveEngineView.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.HiveEngine.Views/3.3/HiveEngineView.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.HiveEngine.Views/3.3/HiveEngineView.cs	(revision 6725)
@@ -81,5 +81,5 @@
         executionTimeOnHiveTextBox.Text = Content.ExecutionTimeOnHive.ToString();
         isPrivilegedCheckBox.Checked = Content.IsPrivileged;
-        hiveExperimentListView.Content = Content.HiveExperiments;
+        hiveExperimentListView.Content = Content.Jobs;
         logView.Content = Content.Log;
       }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.HiveEngine/3.3/HiveEngine.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.HiveEngine/3.3/HiveEngine.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.HiveEngine/3.3/HiveEngine.cs	(revision 6725)
@@ -73,9 +73,9 @@
     }
 
-    // Job can't be storable, so RefreshableHiveExperiment can't be stored. But as previous runs are only informative it does not matter (only execution time on hive will be wrong because of that -> Todo)
-    private ItemCollection<RefreshableHiveExperiment> hiveExperiments = new ItemCollection<RefreshableHiveExperiment>();
-    public ItemCollection<RefreshableHiveExperiment> HiveExperiments {
-      get { return hiveExperiments; }
-      set { hiveExperiments = value; }
+    // Task can't be storable, so RefreshableHiveExperiment can't be stored. But as previous runs are only informative it does not matter (only execution time on hive will be wrong because of that -> Todo)
+    private ItemCollection<RefreshableJob> jobs = new ItemCollection<RefreshableJob>();
+    public ItemCollection<RefreshableJob> Jobs {
+      get { return jobs; }
+      set { jobs = value; }
     }
 
@@ -111,5 +111,5 @@
       this.executionTimeOnHive = original.executionTimeOnHive;
       this.IsPrivileged = original.IsPrivileged;
-      // do not clone hiveExperiments - otherwise they would be sent with every job
+      // do not clone jobs - otherwise they would be sent with every task
     }
     public override IDeepCloneable Clone(Cloner cloner) {
@@ -158,15 +158,15 @@
           if (coll.Parallel) {
             try {
-              // clone the parent scope here and reuse it for each operation. otherwise for each job the whole scope-tree first needs to be copied and then cleaned, which causes a lot of work for the Garbage Collector
+              // clone the parent scope here and reuse it for each operation. otherwise for each task the whole scope-tree first needs to be copied and then cleaned, which causes a lot of work for the Garbage Collector
               IScope parentScopeClone = (IScope)((IAtomicOperation)coll.First()).Scope.Parent.Clone();
               parentScopeClone.SubScopes.Clear();
               parentScopeClone.ClearParentScopes();
 
-              EngineJob[] jobs = new EngineJob[coll.Count];
+              EngineTask[] jobs = new EngineTask[coll.Count];
               for (int i = 0; i < coll.Count; i++) {
-                jobs[i] = new EngineJob(coll[i], new SequentialEngine.SequentialEngine());
+                jobs[i] = new EngineTask(coll[i], new SequentialEngine.SequentialEngine());
               }
 
-              var experiment = CreateHiveExperiment();
+              var experiment = CreateJob();
               IScope[] scopes = ExecuteOnHive(experiment, jobs, parentScopeClone, cancellationToken);
 
@@ -241,16 +241,16 @@
     /// </summary>
     /// <param name="jobs"></param>
-    private IScope[] ExecuteOnHive(RefreshableHiveExperiment refreshableHiveExperiment, EngineJob[] jobs, IScope parentScopeClone, CancellationToken cancellationToken) {
+    private IScope[] ExecuteOnHive(RefreshableJob refreshableJob, EngineTask[] jobs, IScope parentScopeClone, CancellationToken cancellationToken) {
       log.LogMessage(string.Format("Executing {0} operations on the hive.", jobs.Length));
       IScope[] scopes = new Scope[jobs.Length];
       object locker = new object();
-      var hiveExperiment = refreshableHiveExperiment.HiveExperiment;
+      var hiveExperiment = refreshableJob.Job;
 
       try {
         // create upload-tasks
         for (int i = 0; i < jobs.Length; i++) {
-          var engineHiveJob = new EngineHiveJob(jobs[i], parentScopeClone);
-          engineHiveJob.Job.Priority = this.Priority;
-          refreshableHiveExperiment.HiveJobs.Add(engineHiveJob);
+          var engineHiveJob = new EngineHiveTask(jobs[i], parentScopeClone);
+          engineHiveJob.Task.Priority = this.Priority;
+          refreshableJob.HiveJobs.Add(engineHiveJob);
 
           // shuffle random variable to avoid the same random sequence in each operation; todo: does not yet work (it cannot find the random variable)
@@ -259,23 +259,23 @@
             random.Reset(random.Next());
         }
-        HiveClient.StartExperiment((e) => { log.LogException(e); }, refreshableHiveExperiment, cancellationToken);
+        HiveClient.StartExperiment((e) => { log.LogException(e); }, refreshableJob, cancellationToken);
 
         // do polling until experiment is finished and all jobs are downloaded
-        while (!refreshableHiveExperiment.AllJobsFinished()) {
+        while (!refreshableJob.AllJobsFinished()) {
           Thread.Sleep(2000);
-          this.ExecutionTimeOnHive = TimeSpan.FromMilliseconds(hiveExperiments.Sum(x => x.ExecutionTime.TotalMilliseconds));
+          this.ExecutionTimeOnHive = TimeSpan.FromMilliseconds(jobs.Sum(x => x.ExecutionTime.TotalMilliseconds));
           cancellationToken.ThrowIfCancellationRequested();
         }
-        log.LogMessage(string.Format("{0} finished (TotalExecutionTime: {1}).", refreshableHiveExperiment.ToString(), refreshableHiveExperiment.ExecutionTime));
-
-        var failedJobs = refreshableHiveExperiment.HiveJobs.Where(x => x.Job.State == TaskState.Failed);
+        log.LogMessage(string.Format("{0} finished (TotalExecutionTime: {1}).", refreshableJob.ToString(), refreshableJob.ExecutionTime));
+
+        var failedJobs = refreshableJob.HiveJobs.Where(x => x.Task.State == TaskState.Failed);
         if (failedJobs.Count() > 0) {
-          throw new HiveEngineException("Task failed: " + failedJobs.First().Job.StateLog.Last().Exception);
+          throw new HiveEngineException("Task failed: " + failedJobs.First().Task.StateLog.Last().Exception);
         }
 
         // get scopes
         int j = 0;
-        foreach (var hiveJob in refreshableHiveExperiment.HiveJobs) {
-          var scope = ((IAtomicOperation)((EngineJob)hiveJob.ItemJob).InitialOperation).Scope;
+        foreach (var hiveJob in refreshableJob.HiveJobs) {
+          var scope = ((IAtomicOperation)((EngineTask)hiveJob.ItemTask).InitialOperation).Scope;
           scopes[j++] = scope;
         }
@@ -290,30 +290,30 @@
       }
       finally {
-        DisposeHiveExperiment(refreshableHiveExperiment);
-      }
-    }
-
-    private RefreshableHiveExperiment CreateHiveExperiment() {
+        DisposeJob(refreshableJob);
+      }
+    }
+
+    private RefreshableJob CreateJob() {
       lock (locker) {
         var hiveExperiment = new Job();
-        hiveExperiment.Name = "HiveEngine Run " + hiveExperiments.Count;
+        hiveExperiment.Name = "HiveEngine Run " + jobs.Count;
         hiveExperiment.DateCreated = DateTime.Now;
         hiveExperiment.ResourceNames = this.ResourceNames;
         hiveExperiment.IsPrivileged = this.IsPrivileged;
-        var refreshableHiveExperiment = new RefreshableHiveExperiment(hiveExperiment);
+        var refreshableHiveExperiment = new RefreshableJob(hiveExperiment);
         refreshableHiveExperiment.IsDownloadable = false; // download happens automatically so disable button
-        hiveExperiments.Add(refreshableHiveExperiment);
+        jobs.Add(refreshableHiveExperiment);
         return refreshableHiveExperiment;
       }
     }
 
-    private void DisposeHiveExperiment(RefreshableHiveExperiment refreshableHiveExperiment) {
-      refreshableHiveExperiment.RefreshAutomatically = false;
-      DeleteHiveExperiment(refreshableHiveExperiment.HiveExperiment.Id);
-      ClearData(refreshableHiveExperiment);
-    }
-
-    private void ClearData(RefreshableHiveExperiment refreshableHiveExperiment) {
-      var jobs = refreshableHiveExperiment.GetAllHiveJobs();
+    private void DisposeJob(RefreshableJob refreshableJob) {
+      refreshableJob.RefreshAutomatically = false;
+      DeleteHiveExperiment(refreshableJob.Job.Id);
+      ClearData(refreshableJob);
+    }
+
+    private void ClearData(RefreshableJob refreshableJob) {
+      var jobs = refreshableJob.GetAllHiveJobs();
       foreach (var job in jobs) {
         job.ClearData();
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.HiveEngine/3.3/Tests/Program.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.HiveEngine/3.3/Tests/Program.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.HiveEngine/3.3/Tests/Program.cs	(revision 6725)
@@ -33,8 +33,8 @@
       ContentManager.Initialize(new PersistenceContentManager());
 
-      OptimizerJob job = new OptimizerJob(new Experiment());
+      OptimizerTask job = new OptimizerTask(new Experiment());
       job.IndexInParentOptimizerList = 15;
 
-      //byte[] data = PersistenceUtil.Serialize(job);
+      //byte[] data = PersistenceUtil.Serialize(task);
 
       //var job2 = PersistenceUtil.Deserialize<OptimizerJob>(data);
@@ -66,5 +66,5 @@
         Console.WriteLine("Log:");
         Console.WriteLine(string.Join(Environment.NewLine, alg.Engine.Log.Messages.ToArray()));
-        var exps = ((HiveEngine)alg.Engine).HiveExperiments;
+        var exps = ((HiveEngine)alg.Engine).Jobs;
         foreach (var exp in exps) {
           Console.WriteLine("# " + exp.ToString());
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Tests/ServiceTests.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Tests/ServiceTests.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Tests/ServiceTests.cs	(revision 6725)
@@ -51,5 +51,5 @@
       DT.Job experiment = new DT.Job() { Name = "TestExperiment", Description = "" };
 
-      // create job
+      // create task
       DT.Task job = new DT.Task() { CoresNeeded = 1, MemoryNeeded = 0, Priority = 0 };
       job.State = DT.TaskState.Offline;
@@ -100,9 +100,9 @@
       experiment.Id = service.AddHiveExperiment(experiment);
 
-      // add job
+      // add task
       job.JobId = experiment.Id;
       job.Id = service.AddJob(job, jobData, new List<Guid> { slave.Id });
 
-      // test job
+      // test task
       DT.Task jobLoaded = service.GetJob(job.Id);
       Assert.AreEqual(job.Id, jobLoaded.Id);
@@ -127,5 +127,5 @@
       var actions = service.Heartbeat(new DT.Heartbeat() { SlaveId = slave.Id, AssignJob = true, FreeCores = 4, FreeMemory = 1024, JobProgress = new Dictionary<Guid, TimeSpan>() });
       Assert.AreEqual(1, actions.Count);
-      Assert.AreEqual(MessageContainer.MessageType.CalculateJob, actions[0].Message);
+      Assert.AreEqual(MessageContainer.MessageType.CalculateTask, actions[0].Message);
       Assert.AreEqual(job.Id, actions[0].TaskId);
 
@@ -142,10 +142,10 @@
       Assert.AreEqual(0, actions.Count);
 
-      // the job should be in state 'Calculating' now
+      // the task should be in state 'Calculating' now
       jobLoaded = service.GetJob(job.Id);
       Assert.AreEqual(TaskState.Calculating, jobLoaded.State);
       Assert.AreEqual(new TimeSpan(1, 5, 10, 20, 30), jobLoaded.ExecutionTime);
 
-      // test if the job is returned for the resource
+      // test if the task is returned for the resource
       var jobsBySlave = service.GetJobsByResourceId(slave.Id);
       Assert.AreEqual(1, jobsBySlave.Count());
@@ -155,15 +155,15 @@
       service.UpdateJobState(jobLoaded.Id, DT.TaskState.Finished, slave.Id, null, null);
 
-      // test if the job is returned for the resource (it should not be)
+      // test if the task is returned for the resource (it should not be)
       var jobsBySlave2 = service.GetJobsByResourceId(slave.Id);
       Assert.AreEqual(0, jobsBySlave2.Count());
 
-      // set job waiting again
+      // set task waiting again
       service.UpdateJobState(job.Id, DT.TaskState.Waiting, null, null, string.Empty);
 
-      // get job again
+      // get task again
       actions = service.Heartbeat(new DT.Heartbeat() { SlaveId = slave.Id, AssignJob = true, FreeCores = 4, FreeMemory = 1024, JobProgress = new Dictionary<Guid, TimeSpan>() });
       Assert.AreEqual(1, actions.Count);
-      Assert.AreEqual(MessageContainer.MessageType.CalculateJob, actions[0].Message);
+      Assert.AreEqual(MessageContainer.MessageType.CalculateTask, actions[0].Message);
       Assert.AreEqual(job.Id, actions[0].TaskId);
 
@@ -186,8 +186,8 @@
       Assert.AreEqual(null, service.GetJobData(job.Id));
 
-      // send another heartbeat with the deleted job; the server should command the abortion of the job
+      // send another heartbeat with the deleted task; the server should command the abortion of the task
       actions = service.Heartbeat(new DT.Heartbeat() { SlaveId = slave.Id, AssignJob = true, FreeCores = 3, FreeMemory = 1024, JobProgress = progress });
       Assert.AreEqual(1, actions.Count);
-      Assert.AreEqual(MessageContainer.MessageType.AbortJob, actions[0].Message);
+      Assert.AreEqual(MessageContainer.MessageType.AbortTask, actions[0].Message);
       Assert.AreEqual(job.Id, actions[0].TaskId);
 
@@ -203,10 +203,10 @@
       DT.Job experiment = new DT.Job() { Name = "TestExperiment", Description = "" };
 
-      // create parent job
+      // create parent task
       DT.Task parentJob = new DT.Task() {
         CoresNeeded = 1,
         MemoryNeeded = 0,
         Priority = 0,
-        IsParentJob = true,
+        IsParentTask = true,
         FinishWhenChildJobsFinished = true
       };
@@ -216,5 +216,5 @@
       DT.TaskData parentJobData = new DT.TaskData() { Data = new byte[0] };
 
-      // create child job
+      // create child task
       DT.Task childJob = new DT.Task() {
         CoresNeeded = 1,
@@ -243,14 +243,14 @@
       experiment.Id = service.AddHiveExperiment(experiment);
 
-      // add parent job
+      // add parent task
       parentJob.JobId = experiment.Id;
       parentJob.Id = service.AddJob(parentJob, parentJobData, new List<Guid> { slave.Id });
 
-      // add child job
+      // add child task
       childJob.JobId = experiment.Id;
       childJob.Id = service.AddChildJob(parentJob.Id, childJob, childJobData);
       childJob.ParentTaskId = parentJob.Id;
 
-      // test child job
+      // test child task
       var childJobLoaded = service.GetJob(childJob.Id);
       Assert.AreEqual(childJob.ParentTaskId, childJobLoaded.ParentTaskId);
@@ -258,20 +258,20 @@
       Assert.AreEqual(DT.TaskState.Waiting, childJobLoaded.State);
       Assert.AreEqual(false, childJobLoaded.FinishWhenChildJobsFinished);
-      Assert.AreEqual(false, childJobLoaded.IsParentJob);
-
-      // test parent job
+      Assert.AreEqual(false, childJobLoaded.IsParentTask);
+
+      // test parent task
       var parentJobLoaded = service.GetJob(parentJob.Id);
       Assert.AreEqual(parentJob.JobId, parentJobLoaded.JobId);
       Assert.AreEqual(TaskState.Waiting, parentJobLoaded.State);
       Assert.AreEqual(true, parentJobLoaded.FinishWhenChildJobsFinished);
-      Assert.AreEqual(true, parentJobLoaded.IsParentJob);
+      Assert.AreEqual(true, parentJobLoaded.IsParentTask);
 
       // test heartbeat
       var actions = service.Heartbeat(new DT.Heartbeat() { SlaveId = slave.Id, AssignJob = true, FreeCores = 4, FreeMemory = 1024, JobProgress = new Dictionary<Guid, TimeSpan>() });
-      Assert.AreEqual(1, actions.Count); // only the child job should be assigned
-      Assert.AreEqual(MessageContainer.MessageType.CalculateJob, actions[0].Message);
+      Assert.AreEqual(1, actions.Count); // only the child task should be assigned
+      Assert.AreEqual(MessageContainer.MessageType.CalculateTask, actions[0].Message);
       Assert.AreEqual(childJob.Id, actions[0].TaskId);
 
-      // lifecycle - let it process one server-heartbeat; the parent job must NOT be set to finished
+      // lifecycle - let it process one server-heartbeat; the parent task must NOT be set to finished
       service.TriggerEventManager(true);
 
@@ -279,11 +279,11 @@
       Assert.AreEqual(TaskState.Waiting, parentJobLoaded.State);
 
-      // set child job to finished
+      // set child task to finished
       childJobLoaded = service.UpdateJobState(childJobLoaded.Id, DT.TaskState.Finished, slave.Id, null, null);
 
-      // lifecycle - let it process one server-heartbeat; this should set the parent job to finished
+      // lifecycle - let it process one server-heartbeat; this should set the parent task to finished
       service.TriggerEventManager(true);
 
-      // test if parent job is finished
+      // test if parent task is finished
       parentJobLoaded = service.GetJob(parentJob.Id);
       Assert.AreEqual(TaskState.Finished, parentJobLoaded.State);
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.3/Convert.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.3/Convert.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.3/Convert.cs	(revision 6725)
@@ -44,5 +44,5 @@
         State = Convert.ToDto(source.State),
         StateLog = (source.StateLogs == null ? new List<DT.StateLog>() : source.StateLogs.Select(x => Convert.ToDto(x)).OrderBy(x => x.DateTime).ToList()),
-        IsParentJob = source.IsParentTask,
+        IsParentTask = source.IsParentTask,
         FinishWhenChildJobsFinished = source.FinishWhenChildJobsFinished,
         Command = Convert.ToDto(source.Command),
@@ -72,5 +72,5 @@
           target.StateLogs.Add(Convert.ToEntity(sl));
         }
-        target.IsParentTask = source.IsParentJob;
+        target.IsParentTask = source.IsParentTask;
         target.FinishWhenChildJobsFinished = source.FinishWhenChildJobsFinished;
         target.Command = Convert.ToEntity(source.Command);
@@ -82,5 +82,5 @@
     #endregion
 
-    #region JobData
+    #region TaskData
     public static DT.TaskData ToDto(DB.TaskData source) {
       if (source == null) return null;
@@ -133,5 +133,5 @@
     #endregion
 
-    #region HiveExperiment
+    #region Job
     public static DT.Job ToDto(DB.Job source) {
       if (source == null) return null;
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.3/DataTransfer/Task.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.3/DataTransfer/Task.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.3/DataTransfer/Task.cs	(revision 6725)
@@ -39,5 +39,5 @@
     public DateTime? LastHeartbeat { get; set; }
     [DataMember]
-    public bool IsParentJob { get; set; }
+    public bool IsParentTask { get; set; }
     [DataMember]
     public bool FinishWhenChildJobsFinished { get; set; }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.3/HiveDao.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.3/HiveDao.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.3/HiveDao.cs	(revision 6725)
@@ -150,5 +150,5 @@
     #endregion
 
-    #region JobData Methods
+    #region TaskData Methods
     public DT.TaskData GetJobData(Guid id) {
       using (var db = CreateContext(true)) {
@@ -230,5 +230,5 @@
     #endregion
 
-    #region HiveExperiment Methods
+    #region Job Methods
     public DT.Job GetHiveExperiment(Guid id) {
       using (var db = CreateContext()) {
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.3/HiveService.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.3/HiveService.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.3/HiveService.cs	(revision 6725)
@@ -196,5 +196,5 @@
     #endregion
 
-    #region Job Control Methods
+    #region Task Control Methods
     public void StopJob(Guid jobId) {
       authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client, HiveRoles.Slave);
@@ -238,5 +238,5 @@
     #endregion
 
-    #region HiveExperiment Methods
+    #region Job Methods
     public Job GetHiveExperiment(Guid id) {
       authen.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.3/Interfaces/IHiveDao.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.3/Interfaces/IHiveDao.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.3/Interfaces/IHiveDao.cs	(revision 6725)
@@ -28,5 +28,5 @@
 namespace HeuristicLab.Services.Hive {
   public interface IHiveDao {
-    #region Job Methods
+    #region Task Methods
     DT.Task GetJob(Guid id);
     IEnumerable<DT.Task> GetJobs(Expression<Func<Task, bool>> predicate);
@@ -39,5 +39,5 @@
     #endregion
 
-    #region JobData Methods
+    #region TaskData Methods
     DT.TaskData GetJobData(Guid id);
     IEnumerable<DT.TaskData> GetJobDatas(Expression<Func<TaskData, bool>> predicate);
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.3/Manager/HeartbeatManager.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.3/Manager/HeartbeatManager.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.3/Manager/HeartbeatManager.cs	(revision 6725)
@@ -63,5 +63,5 @@
             var job = availableJobs.First();
             if (AssignJob(slave, job))
-              actions.Add(new MessageContainer(MessageContainer.MessageType.CalculateJob, job.Id));
+              actions.Add(new MessageContainer(MessageContainer.MessageType.CalculateTask, job.Id));
           }
         }
@@ -101,14 +101,14 @@
           if (curJob == null) {
             // job does not exist in db
-            actions.Add(new MessageContainer(MessageContainer.MessageType.AbortJob, jobProgress.Key));
+            actions.Add(new MessageContainer(MessageContainer.MessageType.AbortTask, jobProgress.Key));
             DA.LogFactory.GetLogger(this.GetType().Namespace).Log("Job does not exist in DB: " + jobProgress.Key);
           } else {
             if (curJob.CurrentStateLog.SlaveId == Guid.Empty || curJob.CurrentStateLog.SlaveId != heartbeat.SlaveId) {
               // assigned slave does not match heartbeat
-              actions.Add(new MessageContainer(MessageContainer.MessageType.AbortJob, curJob.Id));
+              actions.Add(new MessageContainer(MessageContainer.MessageType.AbortTask, curJob.Id));
               DA.LogFactory.GetLogger(this.GetType().Namespace).Log("The slave " + heartbeat.SlaveId + " is not supposed to calculate Job: " + curJob);
             } else if (!JobIsAllowedToBeCalculatedBySlave(heartbeat.SlaveId, curJob)) {
               // assigned resources ids of job do not match with slaveId (and parent resourceGroupIds); this might happen when slave is moved to different group
-              actions.Add(new MessageContainer(MessageContainer.MessageType.PauseJob, curJob.Id));
+              actions.Add(new MessageContainer(MessageContainer.MessageType.PauseTask, curJob.Id));
             } else {
               // save job execution time
@@ -118,11 +118,11 @@
               switch (curJob.Command) {
                 case Command.Stop:
-                  actions.Add(new MessageContainer(MessageContainer.MessageType.StopJob, curJob.Id));
+                  actions.Add(new MessageContainer(MessageContainer.MessageType.StopTask, curJob.Id));
                   break;
                 case Command.Pause:
-                  actions.Add(new MessageContainer(MessageContainer.MessageType.PauseJob, curJob.Id));
+                  actions.Add(new MessageContainer(MessageContainer.MessageType.PauseTask, curJob.Id));
                   break;
                 case Command.Abort:
-                  actions.Add(new MessageContainer(MessageContainer.MessageType.AbortJob, curJob.Id));
+                  actions.Add(new MessageContainer(MessageContainer.MessageType.AbortTask, curJob.Id));
                   break;
               }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.3/MessageContainer.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.3/MessageContainer.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.3/MessageContainer.cs	(revision 6725)
@@ -37,10 +37,10 @@
     public enum MessageType {
       // *** commands from hive server ***
-      CalculateJob, // slave should calculate a job. the job is already assigned to the slave
-      StopJob,   // slave should stop the job and submit results
+      CalculateTask, // slave should calculate a job. the job is already assigned to the slave
+      StopTask,   // slave should stop the job and submit results
       StopAll,   // stop all and submit results
-      AbortJob,  // slave should shut the job down immediately without submitting results
+      AbortTask,  // slave should shut the job down immediately without submitting results
       AbortAll,  // slave should abort all jobs immediately
-      PauseJob,  // pause the job and submit the results   
+      PauseTask,  // pause the job and submit the results   
       PauseAll,  // pause all jobs and submit results
       Restart,   // restart operation after Sleep
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.3/ServiceContracts/IHiveService.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.3/ServiceContracts/IHiveService.cs	(revision 6723)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive/3.3/ServiceContracts/IHiveService.cs	(revision 6725)
@@ -31,57 +31,57 @@
   public interface IHiveService {
 
+    #region Task Methods
+    [OperationContract]
+    Guid AddJob(Task job, TaskData jobData, IEnumerable<Guid> resourceIds);
+
+    [OperationContract]
+    Guid AddChildJob(Guid parentJobId, Task job, TaskData jobData);
+
+    [OperationContract]
+    Task GetJob(Guid jobId);
+
+    [OperationContract]
+    IEnumerable<Task> GetJobs();
+
+    [OperationContract]
+    IEnumerable<LightweightTask> GetLightweightJobs(IEnumerable<Guid> jobIds);
+
+    [OperationContract]
+    IEnumerable<LightweightTask> GetLightweightChildJobs(Guid? parentJobId, bool recursive, bool includeParent);
+
+    [OperationContract]
+    IEnumerable<LightweightTask> GetLightweightExperimentJobs(Guid experimentId);
+
+    [OperationContract]
+    TaskData GetJobData(Guid jobId);
+
+    [OperationContract]
+    void UpdateJob(Task jobDto);
+
+    [OperationContract]
+    void UpdateJobData(Task jobDto, TaskData jobDataDto);
+
+    [OperationContract]
+    void DeleteJob(Guid jobId);
+
+    [OperationContract]
+    void DeleteChildJobs(Guid parentJobId);
+
+    [OperationContract]
+    Task UpdateJobState(Guid jobId, TaskState jobState, Guid? slaveId, Guid? userId, string exception);
+    #endregion
+
+    #region Job Control Methods
+    [OperationContract]
+    void StopJob(Guid jobId);
+
+    [OperationContract]
+    void PauseJob(Guid jobId);
+
+    [OperationContract]
+    void RestartJob(Guid jobId);
+    #endregion
+
     #region Job Methods
-    [OperationContract]
-    Guid AddJob(Task job, TaskData jobData, IEnumerable<Guid> resourceIds);
-
-    [OperationContract]
-    Guid AddChildJob(Guid parentJobId, Task job, TaskData jobData);
-
-    [OperationContract]
-    Task GetJob(Guid jobId);
-
-    [OperationContract]
-    IEnumerable<Task> GetJobs();
-
-    [OperationContract]
-    IEnumerable<LightweightTask> GetLightweightJobs(IEnumerable<Guid> jobIds);
-
-    [OperationContract]
-    IEnumerable<LightweightTask> GetLightweightChildJobs(Guid? parentJobId, bool recursive, bool includeParent);
-
-    [OperationContract]
-    IEnumerable<LightweightTask> GetLightweightExperimentJobs(Guid experimentId);
-
-    [OperationContract]
-    TaskData GetJobData(Guid jobId);
-
-    [OperationContract]
-    void UpdateJob(Task jobDto);
-
-    [OperationContract]
-    void UpdateJobData(Task jobDto, TaskData jobDataDto);
-
-    [OperationContract]
-    void DeleteJob(Guid jobId);
-
-    [OperationContract]
-    void DeleteChildJobs(Guid parentJobId);
-
-    [OperationContract]
-    Task UpdateJobState(Guid jobId, TaskState jobState, Guid? slaveId, Guid? userId, string exception);
-    #endregion
-
-    #region Job Control Methods
-    [OperationContract]
-    void StopJob(Guid jobId);
-
-    [OperationContract]
-    void PauseJob(Guid jobId);
-
-    [OperationContract]
-    void RestartJob(Guid jobId);
-    #endregion
-
-    #region HiveExperiment Methods
     [OperationContract]
     Job GetHiveExperiment(Guid id);
