Index: trunk/sources/HeuristicLab.CEDMA.DB/Database.cs
===================================================================
--- trunk/sources/HeuristicLab.CEDMA.DB/Database.cs	(revision 379)
+++ trunk/sources/HeuristicLab.CEDMA.DB/Database.cs	(revision 380)
@@ -30,4 +30,5 @@
 using System.Data.SQLite;
 using System.Data.Common;
+using System.Threading;
 
 namespace HeuristicLab.CEDMA.DB {
@@ -35,12 +36,14 @@
   public class Database : IDatabase {
     private string connectionString;
-    private object bigLock = new object();
+    private ReaderWriterLockSlim rwLock;
     public Database(string connectionString) {
       this.connectionString = connectionString;
+      rwLock = new ReaderWriterLockSlim();
     }
 
     #region create empty database
     public void CreateNew() {
-      lock(bigLock) {
+      rwLock.EnterWriteLock();
+      try {
         using(DbConnection cnn = new SQLiteConnection(connectionString)) {
           cnn.Open();
@@ -69,4 +72,6 @@
           }
         }
+      } finally {
+        rwLock.ExitWriteLock();
       }
     }
@@ -75,5 +80,6 @@
     #region insert agent/run/result/sub-result
     public long InsertAgent(string name, byte[] rawData) {
-      lock(bigLock) {
+      rwLock.EnterWriteLock();
+      try {
         using(DbConnection cnn = new SQLiteConnection(connectionString)) {
           cnn.Open();
@@ -97,9 +103,12 @@
           }
         }
+      } finally {
+        rwLock.ExitWriteLock();
       }
     }
 
     public long InsertRun(long agentId, byte[] rawData) {
-      lock(bigLock) {
+      rwLock.EnterWriteLock();
+      try {
         using(SQLiteConnection cnn = new SQLiteConnection(connectionString)) {
           cnn.Open();
@@ -128,9 +137,12 @@
           }
         }
+      } finally {
+        rwLock.ExitWriteLock();
       }
     }
 
     public long InsertResult(long runId, byte[] rawData) {
-      lock(bigLock) {
+      rwLock.EnterWriteLock();
+      try {
         using(SQLiteConnection cnn = new SQLiteConnection(connectionString)) {
           cnn.Open();
@@ -159,10 +171,12 @@
           }
         }
+      } finally {
+        rwLock.ExitWriteLock();
       }
     }
 
     public long InsertSubResult(long resultId, byte[] rawData) {
-      lock(bigLock) {
-
+      rwLock.EnterWriteLock();
+      try {
         using(SQLiteConnection cnn = new SQLiteConnection(connectionString)) {
           cnn.Open();
@@ -191,4 +205,6 @@
           }
         }
+      } finally {
+        rwLock.ExitWriteLock();
       }
     }
@@ -197,5 +213,6 @@
     #region update agent/run
     public void UpdateAgent(long id, string name) {
-      lock(bigLock) {
+      rwLock.EnterWriteLock();
+      try {
         using(SQLiteConnection cnn = new SQLiteConnection(connectionString)) {
           cnn.Open();
@@ -217,9 +234,12 @@
           }
         }
+      } finally {
+        rwLock.ExitWriteLock();
       }
     }
 
     public void UpdateAgent(long id, ProcessStatus status) {
-      lock(bigLock) {
+      rwLock.EnterWriteLock();
+      try {
         using(SQLiteConnection cnn = new SQLiteConnection(connectionString)) {
           cnn.Open();
@@ -241,9 +261,12 @@
           }
         }
+      } finally {
+        rwLock.ExitWriteLock();
       }
     }
 
     public void UpdateAgent(long id, byte[] rawData) {
-      lock(bigLock) {
+      rwLock.EnterWriteLock();
+      try {
         using(SQLiteConnection cnn = new SQLiteConnection(connectionString)) {
           cnn.Open();
@@ -265,9 +288,12 @@
           }
         }
+      } finally {
+        rwLock.ExitWriteLock();
       }
     }
 
     public void UpdateRunStart(long runId, DateTime startTime) {
-      lock(bigLock) {
+      rwLock.EnterWriteLock();
+      try {
         using(SQLiteConnection cnn = new SQLiteConnection(connectionString)) {
           cnn.Open();
@@ -289,9 +315,12 @@
           }
         }
+      } finally {
+        rwLock.ExitWriteLock();
       }
     }
 
     public void UpdateRunFinished(long runId, DateTime finishedTime) {
-      lock(bigLock) {
+      rwLock.EnterWriteLock();
+      try {
         using(SQLiteConnection cnn = new SQLiteConnection(connectionString)) {
           cnn.Open();
@@ -313,9 +342,12 @@
           }
         }
+      } finally {
+        rwLock.ExitWriteLock();
       }
     }
 
     public void UpdateRunStatus(long runId, ProcessStatus status) {
-      lock(bigLock) {
+      rwLock.EnterWriteLock();
+      try {
         using(SQLiteConnection cnn = new SQLiteConnection(connectionString)) {
           cnn.Open();
@@ -337,17 +369,16 @@
           }
         }
-      }
-    }
-
-
-
+      } finally {
+        rwLock.ExitWriteLock();
+      }
+    }
     #endregion
 
-
     #region get agent/run/result/sub-result
 
     public ICollection<AgentEntry> GetAgents(ProcessStatus status) {
-      lock(bigLock) {
-        List<AgentEntry> agents = new List<AgentEntry>();
+      rwLock.EnterReadLock();
+      List<AgentEntry> agents = new List<AgentEntry>();
+      try {
         using(SQLiteConnection cnn = new SQLiteConnection(connectionString)) {
           cnn.Open();
@@ -369,11 +400,14 @@
           }
         }
-        return agents;
-      }
+      } finally {
+        rwLock.ExitReadLock();
+      }
+      return agents;
     }
 
     public ICollection<AgentEntry> GetAgents() {
-      lock(bigLock) {
-        List<AgentEntry> agents = new List<AgentEntry>();
+      rwLock.EnterReadLock();
+      List<AgentEntry> agents = new List<AgentEntry>();
+      try {
         using(DbConnection cnn = new SQLiteConnection(connectionString)) {
           cnn.Open();
@@ -392,13 +426,14 @@
           }
         }
-        return agents;
-      }
-    }
-
-    //(ID integer primary key autoincrement, AgentId integer, CreationTime DateTime, StartTime DateTime, FinishedTime DateTime, Status text default 'Unknown', RawData Blob)";
+      } finally {
+        rwLock.ExitReadLock();
+      }
+      return agents;
+    }
 
     public ICollection<RunEntry> GetRuns() {
-      lock(bigLock) {
-        List<RunEntry> runs = new List<RunEntry>();
+      List<RunEntry> runs = new List<RunEntry>();
+      rwLock.EnterReadLock();
+      try {
         using(DbConnection cnn = new SQLiteConnection(connectionString)) {
           cnn.Open();
@@ -420,11 +455,14 @@
           }
         }
-        return runs;
-      }
+      } finally {
+        rwLock.ExitReadLock();
+      }
+      return runs;
     }
 
     public ICollection<RunEntry> GetRuns(ProcessStatus status) {
-      lock(bigLock) {
-        List<RunEntry> runs = new List<RunEntry>();
+      List<RunEntry> runs = new List<RunEntry>();
+      rwLock.EnterReadLock();
+      try {
         using(DbConnection cnn = new SQLiteConnection(connectionString)) {
           cnn.Open();
@@ -442,6 +480,6 @@
                 run.AgentId = r.GetInt32(1);
                 run.CreationTime = r.GetDateTime(2);
-                run.StartTime = r.IsDBNull(3)? null : new Nullable<DateTime>(r.GetDateTime(3));
-                run.FinishedTime = r.IsDBNull(4) ? null:new Nullable<DateTime>(r.GetDateTime(4));
+                run.StartTime = r.IsDBNull(3) ? null : new Nullable<DateTime>(r.GetDateTime(3));
+                run.FinishedTime = r.IsDBNull(4) ? null : new Nullable<DateTime>(r.GetDateTime(4));
                 run.Status = (ProcessStatus)Enum.Parse(typeof(ProcessStatus), r.GetString(5));
                 run.RawData = (byte[])r.GetValue(6);
@@ -451,12 +489,14 @@
           }
         }
-        return runs;
-      }
-    }
-
-    // (ID integer primary key autoincrement, RunId integer, ResultId integer, CreationTime DateTime, RawData Blob)";
+      } finally {
+        rwLock.ExitReadLock();
+      }
+      return runs;
+    }
+
     public ICollection<ResultEntry> GetResults(long runId) {
-      lock(bigLock) {
-        List<ResultEntry> results = new List<ResultEntry>();
+      List<ResultEntry> results = new List<ResultEntry>();
+      rwLock.EnterReadLock();
+      try {
         using(DbConnection cnn = new SQLiteConnection(connectionString)) {
           cnn.Open();
@@ -475,6 +515,8 @@
           }
         }
-        return results;
-      }
+      } finally {
+        rwLock.ExitReadLock();
+      }
+      return results;
     }
 
Index: trunk/sources/HeuristicLab.CEDMA.Server/AgentScheduler.cs
===================================================================
--- trunk/sources/HeuristicLab.CEDMA.Server/AgentScheduler.cs	(revision 379)
+++ trunk/sources/HeuristicLab.CEDMA.Server/AgentScheduler.cs	(revision 380)
@@ -46,5 +46,6 @@
         ClearFinishedEngines();
         CreateNewEngines();
-        StepAllEngines();
+        if(engines.Count == 0) Thread.Sleep(10000);
+        else StepAllEngines();
       }
     }
Index: trunk/sources/HeuristicLab.CEDMA.Server/RunScheduler.cs
===================================================================
--- trunk/sources/HeuristicLab.CEDMA.Server/RunScheduler.cs	(revision 379)
+++ trunk/sources/HeuristicLab.CEDMA.Server/RunScheduler.cs	(revision 380)
@@ -37,8 +37,17 @@
     private const int RELEASE_INTERVAL = 5;
     private object remoteCommLock = new object();
+    private object collectionsLock = new object();
+    private Queue<WaitHandle> waithandles;
+    private Dictionary<WaitHandle, AtomicOperation> runningOperations;
+    private Dictionary<WaitHandle, long> runningEntries;
 
     public RunScheduler(Database database, JobManager jobManager) {
       this.database = database;
       this.jobManager = jobManager;
+      runningOperations = new Dictionary<WaitHandle, AtomicOperation>();
+      runningEntries = new Dictionary<WaitHandle, long>();
+      waithandles = new Queue<WaitHandle>();
+      Thread resultsGatheringThread = new Thread(GatherResults);
+      resultsGatheringThread.Start();
     }
     public void Run() {
@@ -64,19 +73,36 @@
         }
 
-        ThreadPool.QueueUserWorkItem(WaitForFinishedRun, new object[] {wHandle, op, entry});
+        lock(collectionsLock) {
+          waithandles.Enqueue(wHandle);
+          runningOperations[wHandle] = op;
+          runningEntries[wHandle] = entry.Id;
+        }
       }
     }
 
-    private void WaitForFinishedRun(object state) {
-      object[] param = (object[])state;
-      WaitHandle wHandle = (WaitHandle)param[0];
-      AtomicOperation op = (AtomicOperation)param[1];
-      RunEntry entry = (RunEntry)param[2];
-      wHandle.WaitOne();
-      wHandle.Close();
-      lock(remoteCommLock) {
-        jobManager.EndExecuteOperation(op);
-        database.UpdateRunStatus(entry.Id, ProcessStatus.Finished);
-        database.UpdateRunFinished(entry.Id, DateTime.Now);
+    private void GatherResults() {
+      while(true) {
+        if(waithandles.Count == 0) Thread.Sleep(1000);
+        else {
+          WaitHandle w;
+          lock(collectionsLock) {
+            w = waithandles.Dequeue();
+          }
+          w.WaitOne();
+          long id;
+          AtomicOperation op;
+          lock(collectionsLock) {
+            id = runningEntries[w];
+            runningEntries.Remove(w);
+            op = runningOperations[w];
+            runningOperations.Remove(w);
+          }
+          w.Close();
+          lock(remoteCommLock) {
+            jobManager.EndExecuteOperation(op);
+            database.UpdateRunStatus(id, ProcessStatus.Finished);
+            database.UpdateRunFinished(id, DateTime.Now);
+          }
+        }
       }
     }
Index: trunk/sources/HeuristicLab.CEDMA.Server/ServerForm.cs
===================================================================
--- trunk/sources/HeuristicLab.CEDMA.Server/ServerForm.cs	(revision 379)
+++ trunk/sources/HeuristicLab.CEDMA.Server/ServerForm.cs	(revision 380)
@@ -56,5 +56,6 @@
     private void InitAgentScheduler() {
       AgentScheduler scheduler = new AgentScheduler(database);
-      ThreadPool.QueueUserWorkItem(delegate(object status) { scheduler.Run(); });
+      Thread agentSchedulerThread = new Thread(scheduler.Run);
+      agentSchedulerThread.Start();
     }
 
@@ -63,5 +64,6 @@
       jobManager.Reset();
       RunScheduler scheduler = new RunScheduler(database, jobManager);
-      ThreadPool.QueueUserWorkItem(delegate(object status) { scheduler.Run(); });
+      Thread runSchedulerThread = new Thread(scheduler.Run);
+      runSchedulerThread.Start();
     }
 
