Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave.Tests/Mocks/MockHiveService.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave.Tests/Mocks/MockHiveService.cs	(revision 5136)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave.Tests/Mocks/MockHiveService.cs	(revision 5137)
@@ -1,13 +1,11 @@
 ﻿using System;
 using System.Collections.Generic;
+using System.IO;
 using System.Linq;
-using System.Text;
+using HeuristicLab.PluginInfrastructure;
+using HeuristicLab.PluginInfrastructure.Manager;
+using HeuristicLab.Services.Hive.Common;
+using HeuristicLab.Services.Hive.Common.DataTransfer;
 using HeuristicLab.Services.Hive.Common.ServiceContracts;
-using HeuristicLab.Services.Hive.Common.DataTransfer;
-using HeuristicLab.Services.Hive.Common;
-using HeuristicLab.PluginInfrastructure.Manager;
-using System.IO;
-using System.Reflection;
-using HeuristicLab.PluginInfrastructure;
 
 namespace HeuristicLab.Clients.Hive.Slave.Tests {
@@ -15,6 +13,8 @@
     private static List<Job> jobs;
     private static List<JobData> jobDatas;
-    private static List<HeuristicLab.Services.Hive.Common.DataTransfer.HiveExperiment> hiveExperiments;    
+    private static List<HeuristicLab.Services.Hive.Common.DataTransfer.HiveExperiment> hiveExperiments;
     private static List<Plugin> plugins = null;
+    public List<Job> ResultJobs { get; set; }
+    public List<JobData> ResultJobDatas { get; set; }
     private static IEnumerable<PluginDescription> pDescs = null;
     private static int cnt = 0;
@@ -28,23 +28,42 @@
       ServerConfigFilePath = Path.Combine(ServerPluginCachePath, "HeuristicLab 3.3.exe.config");
 
-      byte[] data = PersistenceUtil.Serialize(new MockJob(4000, false));
       if (plugins == null)
         plugins = ReadPluginsFromServerCache();
 
-      jobs = new List<Job>();
+
+      //TODO: reuse as fallback?
+      /*jobs = new List<Job>();
       jobs.Add(new Job { Id = Guid.NewGuid(), JobState = JobState.Waiting, DateCreated = DateTime.Now, CoresNeeded = 1, MemoryNeeded = 0 });
       jobs.Add(new Job { Id = Guid.NewGuid(), JobState = JobState.Offline, DateCreated = DateTime.Now, CoresNeeded = 1, MemoryNeeded = 100, ParentJobId = jobs.First().Id });
       jobs.Add(new Job { Id = Guid.NewGuid(), JobState = JobState.Offline, DateCreated = DateTime.Now, CoresNeeded = 1, MemoryNeeded = 1024, ParentJobId = jobs.First().Id });
       jobs.Add(new Job { Id = Guid.NewGuid(), JobState = JobState.Offline, DateCreated = DateTime.Now, CoresNeeded = 1, MemoryNeeded = 4096, ParentJobId = jobs.First().Id });
-
+      byte[] data = PersistenceUtil.Serialize(new MockJob(400, false));
       jobDatas = new List<JobData>();
       foreach (var job in jobs) {
         job.PluginsNeededIds = new List<Guid>();
         job.PluginsNeededIds.AddRange(plugins.Select(a => a.Id));
-        jobDatas.Add(new JobData() { JobId = job.Id, Data = data });        
-      }
-      
+        jobDatas.Add(new JobData() { JobId = job.Id, Data = data });
+      }
+
+      hiveExperiments = new List<HeuristicLab.Services.Hive.Common.DataTransfer.HiveExperiment>();
+      hiveExperiments.Add(new HeuristicLab.Services.Hive.Common.DataTransfer.HiveExperiment() { Id = Guid.NewGuid(), Name = "Hive Exp 1", Description = "", RootJobId = jobs[0].Id });*/
+    }
+
+    public void updateJobs(List<Job> js, MockJob m) {
+      jobs = js;
+      byte[] data = PersistenceUtil.Serialize(m);
+
+      jobDatas = new List<JobData>();
+      foreach (var job in jobs) {
+        job.PluginsNeededIds = new List<Guid>();
+        job.PluginsNeededIds.AddRange(plugins.Select(a => a.Id));
+        jobDatas.Add(new JobData() { JobId = job.Id, Data = data });
+      }
+
       hiveExperiments = new List<HeuristicLab.Services.Hive.Common.DataTransfer.HiveExperiment>();
       hiveExperiments.Add(new HeuristicLab.Services.Hive.Common.DataTransfer.HiveExperiment() { Id = Guid.NewGuid(), Name = "Hive Exp 1", Description = "", RootJobId = jobs[0].Id });
+
+      ResultJobDatas = new List<JobData>();
+      ResultJobs = new List<Job>();
     }
 
@@ -60,4 +79,5 @@
         p.Id = Guid.NewGuid();
         plugins.Add(p);
+
       }
       return plugins;
@@ -87,7 +107,9 @@
       pd.Data = cf;
       return pd;
+
     }
 
     public Job GetJob(Guid jobId) {
+      //MockHBM.SendHeartbeat();
       return jobs.Where(j => j.Id == jobId).SingleOrDefault();
     }
@@ -106,9 +128,13 @@
 
     public JobData GetJobData(Guid jobId) {
-      return jobDatas.Where(jd => jd.JobId == jobId).SingleOrDefault();
+      JobData ret = jobDatas.Where(jd => jd.JobId == jobId).SingleOrDefault();
+      //MockHBM.SendHeartbeat();
+      return ret;
     }
 
     public void UpdateJob(Job jobDto, JobData jobDataDto) {
       Console.WriteLine("Update Job called!");
+      ResultJobDatas.Add(jobDataDto);
+      ResultJobs.Add(jobDto);
     }
 
@@ -123,8 +149,13 @@
 
     #region JobControl Methods
+    int curJobIdx = 0;
     public Job AquireJob(Guid slaveId) {
-      var job = jobs.First();
-      job.SlaveId = slaveId;
-      return job;
+      if (curJobIdx < jobs.Count) {
+        var job = jobs[curJobIdx];
+        job.SlaveId = slaveId;
+        curJobIdx++;
+        return job;
+      }
+      throw new Exception("No Jobs left on MockHiveService!");
     }
 
@@ -169,6 +200,6 @@
     public void GoodBye() {
       // do nothing
-    }    
-    
+    }
+
     public List<MessageContainer> Heartbeat(Heartbeat heartbeat) {
       if (Messages != null && cnt < Messages.Count) {
@@ -178,11 +209,19 @@
       }
     }
-      
+
     #endregion
 
     #region Plugin Methods
-    public Guid AddPlugin(Plugin plugin, List<PluginData> pluginData) {
-      // todo
-      return Guid.NewGuid();
+    public Guid AddPlugin(Plugin p, List<PluginData> pds) {
+      /*p.Id = Guid.NewGuid();
+      plugins.Add(p);
+      foreach (var pluginData in pds) {
+        pluginData.PluginId = p.Id;
+        pluginDatas.Add(pluginData);
+
+      }
+      return p.Id;*/
+      throw new NotImplementedException();
+
     }
 
@@ -190,5 +229,5 @@
       if (plugins == null)
         plugins = ReadPluginsFromServerCache();
-      return plugins;              
+      return plugins;
     }
 
@@ -207,6 +246,6 @@
               pluginDatas.Add(data);
             }
-          }          
-        }     
+          }
+        }
       }
       return pluginDatas;
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave.Tests/Mocks/MockJob.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave.Tests/Mocks/MockJob.cs	(revision 5136)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave.Tests/Mocks/MockJob.cs	(revision 5137)
@@ -114,7 +114,11 @@
         OnJobStopped();
       }
+      catch (ThreadAbortException) {
+        //this happens when the appdomain is killed (e.g. abort from server)
+        Stop();
+      }
       catch (Exception e) {
         this.ExecutionState = Core.ExecutionState.Stopped;
-        OnJobFailed();
+        OnJobFailed(e);
       }
     }
@@ -170,7 +174,8 @@
                                                       
     public event EventHandler JobFailed;
-    protected virtual void OnJobFailed() {
+    protected virtual void OnJobFailed(Exception e) {
       EventHandler handler = JobFailed;
-      if (handler != null) handler(this, EventArgs.Empty);
+      EventArgs<Exception> ev = new EventArgs<Exception>(e);          
+      if (handler != null) handler(this, ev);
     }
 
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave.Tests/SlaveTest.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave.Tests/SlaveTest.cs	(revision 5136)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave.Tests/SlaveTest.cs	(revision 5137)
@@ -1,11 +1,10 @@
 ﻿using System;
-using System.Text;
 using System.Collections.Generic;
 using System.Linq;
+using HeuristicLab.Clients.Common;
+using HeuristicLab.Services.Hive.Common;
+using HeuristicLab.Services.Hive.Common.DataTransfer;
+using HeuristicLab.Services.Hive.Common.ServiceContracts;
 using Microsoft.VisualStudio.TestTools.UnitTesting;
-using HeuristicLab.Clients.Hive.Salve;
-using HeuristicLab.Services.Hive.Common;
-using HeuristicLab.Services.Hive.Common.ServiceContracts;
-using HeuristicLab.Clients.Common;
 
 namespace HeuristicLab.Clients.Hive.Slave.Tests {
@@ -16,9 +15,9 @@
     [ClassInitialize]
     public static void MyClassInitialize(TestContext testContext) {
-      PluginLoader.pluginAssemblies.Any();      
+      PluginLoader.pluginAssemblies.Any();
       ServiceLocator.Instance = new MockServiceLocator();
     }
 
-    public List<List<MessageContainer>> CreateMsgs() {
+    private List<List<MessageContainer>> CreateMsgsForSingleJob() {
       List<List<MessageContainer>> allMsgs = new List<List<MessageContainer>>();
       //get slave to fetch job
@@ -28,4 +27,10 @@
 
       //do nothing
+      msg = new List<MessageContainer>();
+      allMsgs.Add(msg);
+      msg = new List<MessageContainer>();
+      allMsgs.Add(msg);
+      msg = new List<MessageContainer>();
+      allMsgs.Add(msg);
       msg = new List<MessageContainer>();
       allMsgs.Add(msg);
@@ -38,12 +43,131 @@
 
     [TestMethod]
-    public void TestMethod1() {
-      using (Disposable<IHiveService> service = ServiceLocator.Instance.GetService()) { 
-        ((MockHiveService)service.Obj).Messages = CreateMsgs();
+    public void TestSingleJob() {
+      Job testJob = new Job { Id = Guid.NewGuid(), JobState = JobState.Waiting, DateCreated = DateTime.Now, CoresNeeded = 1, MemoryNeeded = 0 };
+      List<Job> jobList = new List<Job>();
+      jobList.Add(testJob);
+      MockJob job = new MockJob(400, false);
+
+      using (Disposable<IHiveService> service = ServiceLocator.Instance.GetService()) {
+        MockHiveService ms = (MockHiveService)service.Obj;
+        ((MockHiveService)service.Obj).Messages = CreateMsgsForSingleJob();
+        ((MockHiveService)service.Obj).updateJobs(jobList, job);
+
+
+        HeuristicLab.Clients.Hive.Salve.Core core = new Salve.Core();
+        core.Start();
+
+        Assert.AreEqual<int>(1, ms.ResultJobs.Count);
+        Assert.AreEqual<Guid>(testJob.Id, ms.ResultJobs[0].Id);
       }
-      
-      HeuristicLab.Clients.Hive.Salve.Core core = new Salve.Core();
-      core.Start();
     }
+
+    private List<List<MessageContainer>> CreateMsgsForShutdownSlaveWhileJobRunning() {
+      List<List<MessageContainer>> allMsgs = new List<List<MessageContainer>>();
+      //get slave to fetch job
+      List<MessageContainer> msg = new List<MessageContainer>();
+      msg.Add(new MessageContainer(MessageContainer.MessageType.AquireJob));
+      allMsgs.Add(msg);
+
+      msg = new List<MessageContainer>();
+      allMsgs.Add(msg);
+
+      msg = new List<MessageContainer>();
+      msg.Add(new MessageContainer(MessageContainer.MessageType.ShutdownSlave));
+      allMsgs.Add(msg);
+      return allMsgs;
+    }
+
+    [TestMethod]
+    public void TestShutdownSlaveWhileJobRunning() {
+      Job testJob = new Job { Id = Guid.NewGuid(), JobState = JobState.Waiting, DateCreated = DateTime.Now, CoresNeeded = 1, MemoryNeeded = 0 };
+      List<Job> jobList = new List<Job>();
+      jobList.Add(testJob);
+      MockJob job = new MockJob(10000, false);
+
+      using (Disposable<IHiveService> service = ServiceLocator.Instance.GetService()) {
+        MockHiveService ms = (MockHiveService)service.Obj;
+        ((MockHiveService)service.Obj).Messages = CreateMsgsForShutdownSlaveWhileJobRunning();
+        ((MockHiveService)service.Obj).updateJobs(jobList, job);
+
+
+        HeuristicLab.Clients.Hive.Salve.Core core = new Salve.Core();
+        core.Start();
+
+      }
+    }
+
+
+    private List<List<MessageContainer>> CreateMsgsForTwoJobs() {
+      List<List<MessageContainer>> allMsgs = new List<List<MessageContainer>>();
+
+      //get slave to fetch jobs
+      List<MessageContainer> msg = new List<MessageContainer>();
+      msg.Add(new MessageContainer(MessageContainer.MessageType.AquireJob));
+      allMsgs.Add(msg);
+
+      msg = new List<MessageContainer>();
+      allMsgs.Add(msg);
+
+      msg = new List<MessageContainer>();
+      msg.Add(new MessageContainer(MessageContainer.MessageType.AquireJob));
+      allMsgs.Add(msg);
+
+
+      msg = new List<MessageContainer>();
+      allMsgs.Add(msg);
+      msg = new List<MessageContainer>();
+      allMsgs.Add(msg);
+      msg = new List<MessageContainer>();
+      allMsgs.Add(msg);
+      msg = new List<MessageContainer>();
+      allMsgs.Add(msg);
+      msg = new List<MessageContainer>();
+      allMsgs.Add(msg);
+      msg = new List<MessageContainer>();
+      allMsgs.Add(msg);
+      msg = new List<MessageContainer>();
+      allMsgs.Add(msg);
+      msg = new List<MessageContainer>();
+      allMsgs.Add(msg);
+      msg = new List<MessageContainer>();
+      allMsgs.Add(msg);
+
+      msg = new List<MessageContainer>();
+      msg.Add(new MessageContainer(MessageContainer.MessageType.ShutdownSlave));
+      allMsgs.Add(msg);
+      return allMsgs;
+    }
+
+    [TestMethod]
+    public void TestTwoJobs() {
+      Job testJob1 = new Job { Id = Guid.NewGuid(), JobState = JobState.Waiting, DateCreated = DateTime.Now, CoresNeeded = 1, MemoryNeeded = 0 };
+      Job testJob2 = new Job { Id = Guid.NewGuid(), JobState = JobState.Waiting, DateCreated = DateTime.Now, CoresNeeded = 1, MemoryNeeded = 0 };
+      List<Job> jobList = new List<Job>();
+      jobList.Add(testJob1);
+      jobList.Add(testJob2);
+      MockJob job = new MockJob(2000, false);
+
+      using (Disposable<IHiveService> service = ServiceLocator.Instance.GetService()) {
+        MockHiveService ms = (MockHiveService)service.Obj;
+        ((MockHiveService)service.Obj).Messages = CreateMsgsForTwoJobs();
+        ((MockHiveService)service.Obj).updateJobs(jobList, job);
+
+
+        HeuristicLab.Clients.Hive.Salve.Core core = new Salve.Core();
+        core.Start();
+        Assert.AreEqual<int>(2, ms.ResultJobs.Count);
+
+      }
+    }
+
+
+
+
+
+
+
+
+
   }
 }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/Core.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/Core.cs	(revision 5136)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/Core.cs	(revision 5137)
@@ -23,10 +23,11 @@
 using System.Collections.Generic;
 using System.IO;
+using System.Runtime.CompilerServices;
 using System.Threading;
+using HeuristicLab.Clients.Hive.Slave;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
+using HeuristicLab.Services.Hive.Common;
 using HeuristicLab.Services.Hive.Common.DataTransfer;
-using HeuristicLab.Services.Hive.Common;
-using HeuristicLab.Clients.Hive.Slave;
 
 
@@ -37,5 +38,4 @@
   public class Core : MarshalByRefObject {
     public static bool abortRequested { get; set; }
-
     public static ILog Log { get; set; }
 
@@ -45,16 +45,7 @@
 
     private WcfService wcfService;
-    private HeartbeatManager heartbeatManager;
-
-    private bool currentlyFetching;
-    private bool CurrentlyFetching {
-      get {
-        return currentlyFetching;
-      }
-      set {
-        currentlyFetching = value;
-        Logger.Debug("Set CurrentlyFetching to " + currentlyFetching);
-      }
-    }
+    public HeartbeatManager heartbeatManager;
+
+    private int coreThreadId;
 
     public Dictionary<Guid, Executor> ExecutionEngines {
@@ -62,6 +53,10 @@
     }
 
-    internal Dictionary<Guid, Job> Jobs {    
+    internal Dictionary<Guid, Job> Jobs {
       get { return jobs; }
+    }
+
+    public Core() {
+      coreThreadId = Thread.CurrentThread.ManagedThreadId;
     }
 
@@ -86,5 +81,5 @@
 
       DeRegisterServiceEvents();
-      
+
       //server.Close();
       Logger.Info("Program shutdown");
@@ -92,5 +87,5 @@
 
     private void StartHeartbeats() {
-      //Initialize the heartbeat
+      //Initialize the heartbeat      
       heartbeatManager = new HeartbeatManager { Interval = new TimeSpan(0, 0, 10) };
       heartbeatManager.StartHeartbeat();
@@ -119,43 +114,37 @@
     private void DetermineAction(MessageContainer container) {
       Logger.Info("Message: " + container.Message.ToString() + " for job: " + container.JobId);
-      switch (container.Message) {
-        //Server requests to abort a job
-        case MessageContainer.MessageType.AbortJob:
-          if (engines.ContainsKey(container.JobId))
-            try {
-              engines[container.JobId].Abort();
-            }
-            catch (AppDomainUnloadedException) {
-              // appdomain already unloaded. Finishing job probably ongoing
-            }
-          else
-            Logger.Error("AbortJob: Engine doesn't exist");
-          break;
-                        
-        //Pull a Job from the Server
-        case MessageContainer.MessageType.AquireJob:          
-          if (!CurrentlyFetching) {
+      //TODO: find a better solution
+      if (container is ExecutorMessageContainer<Guid>) {
+        ExecutorMessageContainer<Guid> c = (ExecutorMessageContainer<Guid>)container;
+        c.execute();
+      } else if (container is MessageContainer) {
+        switch (container.Message) {
+          //Server requests to abort a job
+          case MessageContainer.MessageType.AbortJob:
+            if (engines.ContainsKey(container.JobId))
+              try {
+                engines[container.JobId].Abort();
+              }
+              catch (AppDomainUnloadedException) {
+                // appdomain already unloaded. Finishing job probably ongoing
+              } else
+              Logger.Error("AbortJob: Engine doesn't exist");
+            break;
+
+          //Pull a Job from the Server
+          case MessageContainer.MessageType.AquireJob:
+            Job myJob = wcfService.AquireJob();
             //TODO: handle in own thread!!
-            Job myJob = wcfService.AquireJob();
             JobData jobData = wcfService.GetJobData(myJob.Id);
-            wcfService_GetJobCompleted(myJob, jobData);            
-            CurrentlyFetching = true;
-          } else
-            Logger.Info("Currently fetching, won't fetch this time!");
-          break;
-
-        //A Job has finished and can be sent back to the server
-        case MessageContainer.MessageType.JobStopped:
-          SendFinishedJob(container.JobId);
-          break;
-
-        case MessageContainer.MessageType.JobFailed:
-          SendFinishedJob(container.JobId);
-          break;        
-              
-        //Hard shutdown of the client
-        case MessageContainer.MessageType.ShutdownSlave:
-          ShutdownCore();
-          break;
+            StartJobInAppDomain(myJob, jobData);
+            break;
+
+          //Hard shutdown of the client
+          case MessageContainer.MessageType.ShutdownSlave:
+            ShutdownCore();
+            break;
+        }
+      } else {
+        Logger.Warn("Unknown MessageContainer: " + container);
       }
     }
@@ -163,8 +152,7 @@
     public void ShutdownCore() {
       Logger.Info("Shutdown Signal received");
-      
       Logger.Debug("Stopping heartbeat");
       heartbeatManager.StopHeartBeat();
-      abortRequested = true;     
+      abortRequested = true;
       Logger.Debug("Logging out");
 
@@ -177,23 +165,24 @@
         }
       }
-     
-      WcfService.Instance.Disconnect();    
-    }
-
-    //TODO: make synchronized
-    //TODO: start own thread?
-    //only called when waiting for child jobs?
-    public void PauseJob(JobData data ) {
-      if(!Jobs.ContainsKey(data.JobId)) {
-        //TODO: error handling 
-      }
-      Job job = Jobs[data.JobId];
-      job.JobState = JobState.WaitingForChildJobs;
-
-      wcfService.UpdateJob(job, data);      
-      KillAppDomain(data.JobId);      
-    }
-            
-    
+      WcfService.Instance.Disconnect();
+    }
+
+    /// <summary>
+    /// Pauses a job, which means sending it to the server and killing it locally;
+    /// atm only used when executor is waiting for child jobs
+    /// </summary>
+    /// <param name="data"></param>
+    [MethodImpl(MethodImplOptions.Synchronized)]
+    public void PauseJob(JobData data) {
+      if (!Jobs.ContainsKey(data.JobId)) {
+        Logger.Error("Can't find job with id " + data.JobId);
+      } else {
+        Job job = Jobs[data.JobId];
+        job.JobState = JobState.WaitingForChildJobs;
+        wcfService.UpdateJob(job, data);
+      }
+      KillAppDomain(data.JobId);
+    }
+
     /// <summary>
     /// serializes the finished job and submits it to the server. If, at the time, a network connection is unavailable, the Job gets stored on the disk. 
@@ -201,4 +190,5 @@
     /// </summary>
     /// <param name="jobId"></param>
+    [MethodImpl(MethodImplOptions.Synchronized)]
     public void SendFinishedJob(object jobId) {
       try {
@@ -208,5 +198,5 @@
           Logger.Info("Engine doesn't exist");
           return;
-        }  
+        }
         if (!jobs.ContainsKey(jId)) {
           Logger.Info("Job doesn't exist");
@@ -218,12 +208,12 @@
         cJob.Exception = engines[jId].CurrentException;
         cJob.ExecutionTime = engines[jId].ExecutionTime;
-        
+
         try {
           Logger.Info("Sending the finished job with id: " + jId);
           wcfService.UpdateJob(cJob, sJob);
-          SlaveStatusInfo.JobsProcessed++;          
+          SlaveStatusInfo.JobsProcessed++;
         }
         catch (Exception e) {
-          Logger.Info("Transmitting to server failed. Storing the finished job with id: " + jId + " to hdd (" + e.ToString() + ")");          
+          Logger.Info("Transmitting to server failed. Storing the finished job with id: " + jId + " to hdd (" + e.ToString() + ")");
         }
         finally {
@@ -236,5 +226,5 @@
       }
     }
-  
+
     /// <summary>
     /// A new Job from the wcfService has been received and will be started within a AppDomain.
@@ -242,50 +232,48 @@
     /// <param name="sender"></param>
     /// <param name="e"></param>
-    void wcfService_GetJobCompleted(Job myJob, JobData jobData) {      
-        Logger.Info("Received new job with id " + myJob.Id);
-        String pluginDir = Path.Combine(PluginCache.Instance.PluginTempBaseDir, myJob.Id.ToString());
-        bool pluginsPrepared = false;
-
-        try {       
-          PluginCache.Instance.PreparePlugins(myJob, jobData);
-          Logger.Debug("Plugins fetched for job " + myJob.Id);
-          pluginsPrepared = true;
+    private void StartJobInAppDomain(Job myJob, JobData jobData) {
+      Logger.Info("Received new job with id " + myJob.Id);
+      String pluginDir = Path.Combine(PluginCache.Instance.PluginTempBaseDir, myJob.Id.ToString());
+      bool pluginsPrepared = false;
+
+      try {
+        PluginCache.Instance.PreparePlugins(myJob, jobData);
+        Logger.Debug("Plugins fetched for job " + myJob.Id);
+        pluginsPrepared = true;
+      }
+      catch (Exception exception) {
+        Logger.Error(string.Format("Copying plugins for job {0} failed: {1}", myJob.Id, exception));
+      }
+
+      if (pluginsPrepared) {
+        try {
+          AppDomain appDomain = HeuristicLab.PluginInfrastructure.Sandboxing.SandboxManager.CreateAndInitSandbox(myJob.Id.ToString(), pluginDir, Path.Combine(pluginDir, PluginCache.ConfigFileName));
+          appDomain.UnhandledException += new UnhandledExceptionEventHandler(appDomain_UnhandledException);
+          lock (engines) {
+            if (!jobs.ContainsKey(myJob.Id)) {
+              jobs.Add(myJob.Id, myJob);
+              appDomains.Add(myJob.Id, appDomain);
+              Logger.Debug("Creating AppDomain");
+              Executor engine = (Executor)appDomain.CreateInstanceAndUnwrap(typeof(Executor).Assembly.GetName().Name, typeof(Executor).FullName);
+              Logger.Debug("Created AppDomain");
+              engine.JobId = myJob.Id;
+              engine.core = this;
+              Logger.Debug("Starting Engine for job " + myJob.Id);
+              engines.Add(myJob.Id, engine);
+              engine.Start(jobData.Data);
+              SlaveStatusInfo.JobsFetched++;
+              Logger.Info("Increment FetchedJobs to:" + SlaveStatusInfo.JobsFetched);
+            }
+          }
+          heartbeatManager.AwakeHeartBeatThread();
         }
         catch (Exception exception) {
-          Logger.Error(string.Format("Copying plugins for job {0} failed: {1}", myJob.Id, exception));
-        }
-
-        if (pluginsPrepared) {
-          try {
-            AppDomain appDomain = HeuristicLab.PluginInfrastructure.Sandboxing.SandboxManager.CreateAndInitSandbox(myJob.Id.ToString(), pluginDir, Path.Combine(pluginDir, PluginCache.ConfigFileName));
-            appDomain.UnhandledException += new UnhandledExceptionEventHandler(appDomain_UnhandledException);
-            lock (engines) {
-              if (!jobs.ContainsKey(myJob.Id)) {
-                jobs.Add(myJob.Id, myJob);
-                appDomains.Add(myJob.Id, appDomain);
-                Logger.Debug("Creating AppDomain");
-                Executor engine = (Executor)appDomain.CreateInstanceAndUnwrap(typeof(Executor).Assembly.GetName().Name, typeof(Executor).FullName);
-                Logger.Debug("Created AppDomain");
-                engine.JobId = myJob.Id;
-                engine.core = this;
-                Logger.Debug("Starting Engine for job " + myJob.Id);
-                engines.Add(myJob.Id, engine);
-                engine.Start(jobData.Data);
-                SlaveStatusInfo.JobsFetched++;
-                Logger.Info("Increment FetchedJobs to:" + SlaveStatusInfo.JobsFetched);
-              }
-            }
-            heartbeatManager.AwakeHeartBeatThread();
-          }
-          catch (Exception exception) {
-            Logger.Error("Creating the Appdomain and loading the job failed for job " + myJob.Id);
-            Logger.Error("Error thrown is: ", exception);
-            CurrentlyFetching = false;
-            KillAppDomain(myJob.Id);
-          }
-        }      
-      CurrentlyFetching = false;
-    }
-  
+          Logger.Error("Creating the Appdomain and loading the job failed for job " + myJob.Id);
+          Logger.Error("Error thrown is: ", exception);
+          KillAppDomain(myJob.Id);
+        }
+      }
+    }
+
     public event EventHandler<EventArgs<Exception>> ExceptionOccured;
     private void OnExceptionOccured(Exception e) {
@@ -295,5 +283,5 @@
     }
 
-    void appDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
+    private void appDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
       Logger.Error("Exception in AppDomain: " + e.ExceptionObject.ToString());
       KillAppDomain(new Guid(e.ExceptionObject.ToString()));
@@ -301,47 +289,71 @@
 
     /// <summary>
+    /// Enqueues messages from the executor to the message queue. 
+    /// This is necessary if the core thread has to execute certain actions, e.g.
+    /// killing of an app domain. 
+    /// </summary>
+    /// <typeparam name="T"></typeparam>
+    /// <param name="action"></param>
+    /// <param name="parameter"></param>
+    /// <returns>true if the calling method can continue execution, else false</returns>
+    private bool EnqueueExecutorMessage<T>(Action<T> action, T parameter) {
+      if (Thread.CurrentThread.ManagedThreadId != this.coreThreadId) {
+        ExecutorMessageContainer<T> container = new ExecutorMessageContainer<T>();
+        container.Callback = action;
+        container.CallbackParameter = parameter;
+        MessageQueue.GetInstance().AddMessage(container);
+        return false;
+      } else {
+        return true;
+      }
+    }
+
+    /// <summary>
     /// Kill a appdomain with a specific id.
     /// </summary>
     /// <param name="id">the GUID of the job</param>
+    [MethodImpl(MethodImplOptions.Synchronized)]
     public void KillAppDomain(Guid id) {
-      Logger.Debug("Shutting down Appdomain for Job " + id);
-      lock (engines) {
-        try {
-          if (engines.ContainsKey(id))
-            engines[id].Dispose();
-          if (appDomains.ContainsKey(id)) {
-            appDomains[id].UnhandledException -= new UnhandledExceptionEventHandler(appDomain_UnhandledException);
-
-            int repeat = 5;
-            while (repeat > 0) {
-              try {
-                AppDomain.Unload(appDomains[id]);
-                repeat = 0;
-              }
-              catch (CannotUnloadAppDomainException) {
-                Logger.Error("Could not unload AppDomain, will try again in 1 sec.");
-                Thread.Sleep(1000);
-                repeat--;
-                if (repeat == 0) {
-                  throw; // rethrow and let app crash
+      if (EnqueueExecutorMessage<Guid>(KillAppDomain, id)) {
+        Logger.Debug("Shutting down Appdomain for Job " + id);
+        lock (engines) {
+          try {
+            if (engines.ContainsKey(id)) {
+              engines[id].Dispose();
+              engines.Remove(id);
+            }
+
+            if (appDomains.ContainsKey(id)) {
+              appDomains[id].UnhandledException -= new UnhandledExceptionEventHandler(appDomain_UnhandledException);
+
+              int repeat = 5;
+              while (repeat > 0) {
+                try {
+                  AppDomain.Unload(appDomains[id]);
+                  repeat = 0;
+                }
+                catch (CannotUnloadAppDomainException) {
+                  Logger.Error("Could not unload AppDomain, will try again in 1 sec.");
+                  Thread.Sleep(1000);
+                  repeat--;
+                  if (repeat == 0) {
+                    throw; // rethrow and let app crash
+                  }
                 }
               }
+              appDomains.Remove(id);
             }
-            appDomains.Remove(id);
+
+            jobs.Remove(id);
+            PluginCache.Instance.DeletePluginsForJob(id);
+            GC.Collect();
           }
-
-          engines.Remove(id);
-          jobs.Remove(id);
-          PluginCache.Instance.DeletePluginsForJob(id);
-          GC.Collect();
-        }
-        catch (Exception ex) {
-          Logger.Error("Exception when unloading the appdomain: ", ex);
-        }
-      }
-      GC.Collect();
-    } 
-  }   
-
-
+          catch (Exception ex) {
+            Logger.Error("Exception when unloading the appdomain: ", ex);
+          }
+        }
+        GC.Collect();
+      }
+    }
+  }
 }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/Executor.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/Executor.cs	(revision 5136)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/Executor.cs	(revision 5137)
@@ -21,22 +21,21 @@
 
 using System;
+using System.Collections.Generic;
 using System.Linq;
+using HeuristicLab.Clients.Hive.Slave;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
-using HeuristicLab.Services.Hive.Common;
 using HeuristicLab.Hive;
+using HeuristicLab.PluginInfrastructure;
 using HeuristicLab.Services.Hive.Common.DataTransfer;
-using System.Collections.Generic;
-using HeuristicLab.Clients.Hive.Slave;
-using HeuristicLab.PluginInfrastructure;
-
-                                             
+
+
 namespace HeuristicLab.Clients.Hive.Salve {
   public class Executor : MarshalByRefObject, IDisposable {
     public Guid JobId { get; set; }
     public IJob Job { get; set; }
-    public MessageContainer.MessageType CurrentMessage { get; set; }
-    public Core core { get; set; }    
-        
+    private bool wasJobAborted = false;
+    public Core core { get; set; }
+
     private Exception currentException;
     public String CurrentException {
@@ -49,5 +48,5 @@
       }
     }
-    
+
     public ExecutionState ExecutionState {
       get {
@@ -73,5 +72,5 @@
         RegisterJobEvents();
 
-        if (Job.CollectChildJobs) {          
+        if (Job.CollectChildJobs) {
           IEnumerable<JobData> childjobs = WcfService.Instance.GetChildJobs(JobId);
           Job.Resume(childjobs.Select(j => PersistenceUtil.Deserialize<IJob>(j.Data)));
@@ -82,5 +81,5 @@
       }
       catch (Exception e) {
-        this.currentException = e;        
+        this.currentException = e;
       }
     }
@@ -91,10 +90,10 @@
       }
       catch (Exception e) {
-        this.currentException = e;        
+        this.currentException = e;
       }
     }
 
     public void Abort() {
-      CurrentMessage = MessageContainer.MessageType.AbortJob;
+      wasJobAborted = true;
       if ((ExecutionState == ExecutionState.Started) || (ExecutionState == ExecutionState.Paused)) {
         Job.Stop();
@@ -105,5 +104,4 @@
 
     private void RegisterJobEvents() {
-      //TODO: warum gibt es jobStopped und jobfailed nicht mehr? 
       Job.JobStopped += new EventHandler(Job_JobStopped);
       Job.JobFailed += new EventHandler(Job_JobFailed);
@@ -123,5 +121,5 @@
     private List<Guid> FindPluginsNeeded(IJob obj) {
       List<Guid> guids = new List<Guid>();
-      foreach(IPluginDescription desc in PluginUtil.GetDeclaringPlugins(obj)) {        
+      foreach (IPluginDescription desc in PluginUtil.GetDeclaringPlugins(obj)) {
       }
       throw new NotImplementedException("FindPluginsNeeded for Job_NewChildJob");
@@ -147,9 +145,9 @@
       // Pause the job and send it back to the hive. The server will awake it when all child-jobs are finished
       this.Job.CollectChildJobs = true;
-      
+
       JobData jdata = new JobData();
       jdata.Data = PersistenceUtil.Serialize(Job);
       jdata.JobId = this.JobId;
-      
+
       core.PauseJob(jdata);
     }
@@ -167,6 +165,6 @@
 
     private void Job_JobStopped(object sender, EventArgs e) {
-     if (CurrentMessage == MessageContainer.MessageType.AbortJob) {
-       core.KillAppDomain(JobId);
+      if (wasJobAborted) {
+        core.KillAppDomain(JobId);
       } else {
         core.SendFinishedJob(JobId);
@@ -176,6 +174,6 @@
     public JobData GetFinishedJob() {
       if (Job == null) {
-        throw new InvalidStateException("Job is null"); 
-      }              
+        throw new InvalidStateException("Job is null");
+      }
 
       if (Job.ExecutionState == HeuristicLab.Core.ExecutionState.Started) {
@@ -185,5 +183,5 @@
 
       if (Job.ExecutionState == HeuristicLab.Core.ExecutionState.Started) {
-        throw new InvalidStateException("Job is still running"); 
+        throw new InvalidStateException("Job is still running");
       } else {
         JobData jdata = new JobData();
@@ -192,8 +190,7 @@
         return jdata;
       }
-    }   
-   
+    }
+
     public Executor() {
-      // CurrentMessage = MessageContainer.MessageType.NoMessage; [chn] check usage of 'CurrentMessage'
     }
 
@@ -201,5 +198,4 @@
       if (Job != null)
         DeregisterJobEvents();
-      //Queue = null;
       Job = null;
     }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/ExecutorMessageContainer.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/ExecutorMessageContainer.cs	(revision 5137)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/ExecutorMessageContainer.cs	(revision 5137)
@@ -0,0 +1,59 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2010 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.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Services.Hive.Common {
+  /// <summary>
+  /// This class is used to communicate from the executor to the core, e.g. 
+  /// if the appdomain should be killed
+  /// </summary>
+  [StorableClass]
+  [Serializable]
+  public class ExecutorMessageContainer<CallbackParameterType> : MessageContainer {
+
+    [Storable]
+    public Action<CallbackParameterType> Callback;
+    public CallbackParameterType CallbackParameter;
+
+    public ExecutorMessageContainer() : base() { }
+
+    public ExecutorMessageContainer(MessageType message, Guid parentJobId, Action<CallbackParameterType> callback)
+      : base(message, parentJobId) {
+      this.Callback = callback;
+    }
+
+    protected ExecutorMessageContainer(ExecutorMessageContainer<CallbackParameterType> original, Cloner cloner)
+      : base(original, cloner) {
+      this.Callback = original.Callback;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ExecutorMessageContainer<CallbackParameterType>(this, cloner);
+    }
+
+    public void execute() {
+      Callback(CallbackParameter);
+    }    
+  }      
+}
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/HeartbeatManager.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/HeartbeatManager.cs	(revision 5136)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/HeartbeatManager.cs	(revision 5137)
@@ -21,11 +21,10 @@
 
 using System;
+using System.Collections.Generic;
 using System.Diagnostics;
 using System.Threading;
 using HeuristicLab.Common;
-using HeuristicLab.Clients.Hive.Salve;
+using HeuristicLab.Services.Hive.Common;
 using HeuristicLab.Services.Hive.Common.DataTransfer;
-using HeuristicLab.Services.Hive.Common;
-using System.Collections.Generic;
 
 namespace HeuristicLab.Clients.Hive.Salve {
@@ -49,8 +48,8 @@
     private WcfService wcfService;
 
-    private bool abortThreadPending;
+    private bool threadStopped;
 
     ReaderWriterLockSlim heartBeatThreadIsSleepingLock = new ReaderWriterLockSlim();
-    
+
     /// <summary>
     /// Starts the Heartbeat signal.
@@ -58,6 +57,6 @@
     public void StartHeartbeat() {
       this.waitHandle = new AutoResetEvent(true);
-      wcfService = WcfService.Instance;     
-      abortThreadPending = false;
+      wcfService = WcfService.Instance;
+      threadStopped = false;
       heartBeatThread = new Thread(RunHeartBeatThread);
       heartBeatThread.Start();
@@ -68,18 +67,19 @@
     /// </summary>
     public void StopHeartBeat() {
-      abortThreadPending = true;
+      threadStopped = true;
       waitHandle.Set();
       heartBeatThread.Join();
     }
-    
+
     /// <summary>
     /// use this method to singalize there is work to do (to avoid the waiting period if its clear that actions are required)
     /// </summary>
     public void AwakeHeartBeatThread() {
-      waitHandle.Set();
+      if (!threadStopped)
+        waitHandle.Set();
     }
 
     private void RunHeartBeatThread() {
-      while (!abortThreadPending) {
+      while (!threadStopped) {
         try {
           lock (locker) {
@@ -87,18 +87,17 @@
               wcfService.Connect(ConfigManager.Instance.GetClientInfo()); // Login happens automatically upon successfull connection
             }
-            if(wcfService.ConnState == NetworkEnum.WcfConnState.Connected) {
+            if (wcfService.ConnState == NetworkEnum.WcfConnState.Connected) {
               HeuristicLab.Services.Hive.Common.DataTransfer.Slave info = ConfigManager.Instance.GetClientInfo();
 
-              Heartbeat heartBeatData = new Heartbeat
-              {
+              Heartbeat heartBeatData = new Heartbeat {
                 SlaveId = info.Id,
                 FreeCores = info.Cores.HasValue ? info.Cores.Value - ConfigManager.Instance.GetUsedCores() : 0,
                 FreeMemory = GetFreeMemory(),
-                JobProgress = ConfigManager.Instance.GetExecutionTimeOfAllJobs()                
+                JobProgress = ConfigManager.Instance.GetExecutionTimeOfAllJobs()
               };
-                              
+
               Logger.Debug("Sending Heartbeat: " + heartBeatData);
-              List<MessageContainer> msgs =  wcfService.SendHeartbeat(heartBeatData);
-              
+              List<MessageContainer> msgs = wcfService.SendHeartbeat(heartBeatData);
+
               if (msgs == null) {
                 Logger.Debug("Error getting response from Heartbeat");
@@ -108,7 +107,7 @@
               Logger.Debug("Heartbeat Response received: ");
               msgs.ForEach(mc => Logger.Debug(mc.Message.ToString()));
-              msgs.ForEach(mc => MessageQueue.GetInstance().AddMessage(mc));      
+              msgs.ForEach(mc => MessageQueue.GetInstance().AddMessage(mc));
             }
-          } // lock
+          }
         }
         catch (Exception e) {
@@ -117,10 +116,9 @@
         }
         waitHandle.WaitOne(this.Interval);
-      } // while
+      }
       waitHandle.Close();
-      abortThreadPending = false;
       Logger.Debug("Heartbeat thread stopped");
     }
-         
+
 
     #region Eventhandler
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/HeuristicLab.Clients.Hive.Slave-3.4.csproj
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/HeuristicLab.Clients.Hive.Slave-3.4.csproj	(revision 5136)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/HeuristicLab.Clients.Hive.Slave-3.4.csproj	(revision 5137)
@@ -72,4 +72,5 @@
       <SubType>Code</SubType>
     </Compile>
+    <Compile Include="ExecutorMessageContainer.cs" />
     <Compile Include="MessageQueue.cs" />
     <Compile Include="NetworkEnum.cs" />
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/Logger.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/Logger.cs	(revision 5136)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.4/Logger.cs	(revision 5137)
@@ -1,7 +1,3 @@
 ﻿using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using HeuristicLab.Core;
 
 namespace HeuristicLab.Clients.Hive.Salve {
@@ -11,6 +7,6 @@
   /// TODO: send messages to gui
   /// </summary>
-  internal static class Logger {   
-    private static object locker = new object(); 
+  public static class Logger {
+    private static object locker = new object();
 
     public static void Debug(object message) {
@@ -42,5 +38,5 @@
         Console.WriteLine(message.ToString() + " \n Exception is :" + e.ToString());
       }
-    }   
+    }
   }
 }
Index: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Common/3.4/MessageContainer.cs
===================================================================
--- branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Common/3.4/MessageContainer.cs	(revision 5136)
+++ branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Common/3.4/MessageContainer.cs	(revision 5137)
@@ -43,9 +43,4 @@
       SayHello,  // Slave should say hello, because he is unknown to the server
 
-      // *** events from execution engine ***
-      JobStopped,      // job finished, submit results, unload appdomain
-      JobPaused,       // job paused, submit results, unload appdomain
-      JobFailed,       // job failed with an exception. submit the results, unload appdomain
-
       // *** commands from execution engine ***
       AddChildJob,     // adds a new child job for the provided jobId
