Index: /branches/UnloadJobs/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveJobManagerView.cs
===================================================================
--- /branches/UnloadJobs/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveJobManagerView.cs	(revision 9168)
+++ /branches/UnloadJobs/HeuristicLab.Clients.Hive.JobManager/3.3/Views/HiveJobManagerView.cs	(revision 9169)
@@ -54,5 +54,5 @@
       Content.Refreshing += new EventHandler(Content_Refreshing);
       Content.Refreshed += new EventHandler(Content_Refreshed);
-      Content.HiveExperimentsChanged += new EventHandler(Content_HiveExperimentsChanged);
+      Content.HiveJobsChanged += new EventHandler(Content_HiveJobsChanged);
 
     }
@@ -61,5 +61,5 @@
       Content.Refreshing -= new EventHandler(Content_Refreshing);
       Content.Refreshed -= new EventHandler(Content_Refreshed);
-      Content.HiveExperimentsChanged -= new EventHandler(Content_HiveExperimentsChanged);
+      Content.HiveJobsChanged -= new EventHandler(Content_HiveJobsChanged);
       base.DeregisterContentEvents();
     }
@@ -123,10 +123,12 @@
 
     protected override void OnClosing(FormClosingEventArgs e) {
-      base.OnClosing(e);
-      if (Content != null && Content.Jobs != null) {
-        foreach (var exp in Content.Jobs.OfType<RefreshableJob>()) {
-          if (exp.RefreshAutomatically) {
-            exp.RefreshAutomatically = false; // stop result polling
-          }
+      if (Content.Jobs.Any(x => x.IsProgressing)) {
+        MessageBox.Show("The Hive Job Manager can only be closed after all down/uploads are finished. ", "HeuristicLab Hive Job Manager", MessageBoxButtons.OK, MessageBoxIcon.Information);
+        e.Cancel = true;
+      } else {
+        base.OnClosing(e);
+        if (Content != null && Content.Jobs != null) {
+          Content.Jobs.ItemsRemoved -= new CollectionItemsChangedEventHandler<RefreshableJob>(HiveExperiments_ItemsRemoved);
+          Content.ClearHiveClient();
         }
       }
@@ -139,6 +141,8 @@
     }
 
-    private void Content_HiveExperimentsChanged(object sender, EventArgs e) {
-      Content.Jobs.ItemsRemoved += new CollectionItemsChangedEventHandler<RefreshableJob>(HiveExperiments_ItemsRemoved);
+    private void Content_HiveJobsChanged(object sender, EventArgs e) {
+      if (Content.Jobs != null) {
+        Content.Jobs.ItemsRemoved += new CollectionItemsChangedEventHandler<RefreshableJob>(HiveExperiments_ItemsRemoved);
+      }
     }
   }
Index: /branches/UnloadJobs/HeuristicLab.Clients.Hive/3.3/ConcurrentTaskDownloader.cs
===================================================================
--- /branches/UnloadJobs/HeuristicLab.Clients.Hive/3.3/ConcurrentTaskDownloader.cs	(revision 9168)
+++ /branches/UnloadJobs/HeuristicLab.Clients.Hive/3.3/ConcurrentTaskDownloader.cs	(revision 9169)
@@ -30,5 +30,5 @@
   /// 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 {
+  public class ConcurrentTaskDownloader<T> : IDisposable where T : class, ITask {
     private bool abort = false;
     // use semaphore to ensure only few concurrenct connections and few SerializedJob objects in memory
@@ -82,5 +82,6 @@
         if (abort) return null;
         result = HiveServiceLocator.Instance.CallHiveService(s => s.GetTaskData(task.Id));
-      } finally {
+      }
+      finally {
         downloadSemaphore.Release();
       }
@@ -95,5 +96,6 @@
         taskData.Item2.Data = null; // reduce memory consumption.
         return new Tuple<Task, T>(taskData.Item1, deserializedJob);
-      } finally {
+      }
+      finally {
         deserializeSemaphore.Release();
       }
@@ -110,4 +112,12 @@
       if (handler != null) handler(this, new EventArgs<Exception>(exception));
     }
+
+    #region IDisposable Members
+    public void Dispose() {
+      TaskScheduler.UnobservedTaskException -= new EventHandler<UnobservedTaskExceptionEventArgs>(TaskScheduler_UnobservedTaskException);
+      deserializeSemaphore.Dispose();
+      downloadSemaphore.Dispose();
+    }
+    #endregion
   }
 }
Index: /branches/UnloadJobs/HeuristicLab.Clients.Hive/3.3/HiveClient.cs
===================================================================
--- /branches/UnloadJobs/HeuristicLab.Clients.Hive/3.3/HiveClient.cs	(revision 9168)
+++ /branches/UnloadJobs/HeuristicLab.Clients.Hive/3.3/HiveClient.cs	(revision 9169)
@@ -52,5 +52,5 @@
         if (value != jobs) {
           jobs = value;
-          OnHiveExperimentsChanged();
+          OnHiveJobsChanged();
         }
       }
@@ -77,4 +77,18 @@
 
     private HiveClient() { }
+
+    public void ClearHiveClient() {
+      foreach (var j in Jobs) {
+        if (j.RefreshAutomatically) {
+          j.RefreshAutomatically = false; // stop result polling
+          j.Dispose();
+        }
+      }
+      Jobs = null;
+      if (onlinePlugins != null)
+        onlinePlugins.Clear();
+      if (alreadyUploadedPlugins != null)
+        alreadyUploadedPlugins.Clear();
+    }
 
     #region Refresh
@@ -205,7 +219,7 @@
       if (handler != null) handler(this, EventArgs.Empty);
     }
-    public event EventHandler HiveExperimentsChanged;
-    private void OnHiveExperimentsChanged() {
-      var handler = HiveExperimentsChanged;
+    public event EventHandler HiveJobsChanged;
+    private void OnHiveJobsChanged() {
+      var handler = HiveJobsChanged;
       if (handler != null) handler(this, EventArgs.Empty);
     }
@@ -308,6 +322,5 @@
       }
       finally {
-        refreshableJob.RefreshAutomatically = true;
-        refreshableJob.StartResultPolling();
+        //refreshableJob.RefreshAutomatically = true;        
         refreshableJob.Job.Modified = false;
         refreshableJob.IsProgressing = false;
@@ -421,4 +434,5 @@
       refreshableJob.IsProgressing = true;
       refreshableJob.Progress = new Progress();
+      TaskDownloader downloader = null;
 
       try {
@@ -433,5 +447,5 @@
 
         refreshableJob.Progress.Status = "Downloading tasks...";
-        TaskDownloader downloader = new TaskDownloader(allTasks.Select(x => x.Id));
+        downloader = new TaskDownloader(allTasks.Select(x => x.Id));
         downloader.StartAsync();
 
@@ -465,4 +479,7 @@
         refreshableJob.IsProgressing = false;
         refreshableJob.Progress.Finish();
+        if (downloader != null) {
+          downloader.Dispose();
+        }
       }
     }
Index: /branches/UnloadJobs/HeuristicLab.Clients.Hive/3.3/RefreshableJob.cs
===================================================================
--- /branches/UnloadJobs/HeuristicLab.Clients.Hive/3.3/RefreshableJob.cs	(revision 9168)
+++ /branches/UnloadJobs/HeuristicLab.Clients.Hive/3.3/RefreshableJob.cs	(revision 9169)
@@ -31,5 +31,5 @@
 
 namespace HeuristicLab.Clients.Hive {
-  public class RefreshableJob : IHiveItem, IDeepCloneable, IContent, IComparable<RefreshableJob> {
+  public class RefreshableJob : IHiveItem, IDeepCloneable, IContent, IComparable<RefreshableJob>, IDisposable {
     private JobResultPoller jobResultPoller;
     private ConcurrentTaskDownloader<ItemTask> jobDownloader;
@@ -48,5 +48,5 @@
             throw new ArgumentNullException();
 
-          if (job != null) DergisterJobEvents();
+          if (job != null) DeregisterJobEvents();
           job = value;
           if (job != null) {
@@ -66,7 +66,7 @@
       set {
         if (hiveTasks != value) {
-          if (hiveTasks != null) DeregisterHiveJobsEvents();
+          if (hiveTasks != null) DeregisterHiveTasksEvents();
           hiveTasks = value;
-          if (hiveTasks != null) RegisterHiveJobsEvents();
+          if (hiveTasks != null) RegisterHiveTasksEvents();
           OnHiveTasksChanged();
         }
@@ -240,4 +240,5 @@
       if (jobResultPoller != null && jobResultPoller.IsPolling) {
         jobResultPoller.Stop();
+        DeregisterResultPollingEvents();
       }
     }
@@ -358,5 +359,5 @@
     }
 
-    private void DergisterJobEvents() {
+    private void DeregisterJobEvents() {
       job.ToStringChanged -= new EventHandler(OnToStringChanged);
       job.PropertyChanged -= new PropertyChangedEventHandler(job_PropertyChanged);
@@ -473,5 +474,5 @@
 
     #region HiveTasks Events
-    private void RegisterHiveJobsEvents() {
+    private void RegisterHiveTasksEvents() {
       this.hiveTasks.ItemsAdded += new CollectionItemsChangedEventHandler<HiveTask>(hivetasks_ItemsAdded);
       this.hiveTasks.ItemsRemoved += new CollectionItemsChangedEventHandler<HiveTask>(hiveTasks_ItemsRemoved);
@@ -479,5 +480,5 @@
     }
 
-    private void DeregisterHiveJobsEvents() {
+    private void DeregisterHiveTasksEvents() {
       this.hiveTasks.ItemsAdded -= new CollectionItemsChangedEventHandler<HiveTask>(hivetasks_ItemsAdded);
       this.hiveTasks.ItemsRemoved -= new CollectionItemsChangedEventHandler<HiveTask>(hiveTasks_ItemsRemoved);
@@ -605,4 +606,27 @@
       return this.ToString().CompareTo(other.ToString());
     }
+
+    #region IDisposable Members
+    public void Dispose() {
+      if (jobDownloader != null) {
+        jobDownloader.ExceptionOccured -= new EventHandler<EventArgs<Exception>>(jobDownloader_ExceptionOccured);
+        jobDownloader.Dispose();
+        jobDownloader = null;
+      }
+      if (job != null) {
+        DeregisterJobEvents();
+        job = null;
+      }
+      if (hiveTasks != null) {
+        DeregisterHiveTasksEvents();
+        hiveTasks.Clear(); // this should remove the item_StateLogChanged event handlers
+        hiveTasks = null;
+      }
+      if (jobResultPoller != null) {
+        DeregisterResultPollingEvents();
+        jobResultPoller = null;
+      }
+    }
+    #endregion
   }
 }
Index: /branches/UnloadJobs/HeuristicLab.Clients.Hive/3.3/TaskDownloader.cs
===================================================================
--- /branches/UnloadJobs/HeuristicLab.Clients.Hive/3.3/TaskDownloader.cs	(revision 9168)
+++ /branches/UnloadJobs/HeuristicLab.Clients.Hive/3.3/TaskDownloader.cs	(revision 9169)
@@ -23,10 +23,10 @@
 using System.Collections.Generic;
 using System.Linq;
+using System.Threading;
 using HeuristicLab.Clients.Hive.Jobs;
 using HeuristicLab.Common;
-using System.Threading;
 
 namespace HeuristicLab.Clients.Hive {
-  public class TaskDownloader {
+  public class TaskDownloader : IDisposable {
     private IEnumerable<Guid> taskIds;
     private ConcurrentTaskDownloader<ItemTask> taskDownloader;
@@ -38,8 +38,9 @@
     public bool IsFinished {
       get {
-          try {        
-              resultsLock.EnterReadLock();
-              return results.Count == taskIds.Count();
-          } finally { resultsLock.ExitReadLock(); }
+        try {
+          resultsLock.EnterReadLock();
+          return results.Count == taskIds.Count();
+        }
+        finally { resultsLock.ExitReadLock(); }
       }
     }
@@ -59,8 +60,9 @@
     public int FinishedCount {
       get {
-            try {
-              resultsLock.EnterReadLock();
-              return results.Count;
-             } finally { resultsLock.ExitReadLock(); }
+        try {
+          resultsLock.EnterReadLock();
+          return results.Count;
+        }
+        finally { resultsLock.ExitReadLock(); }
       }
     }
@@ -68,8 +70,9 @@
     public IDictionary<Guid, HiveTask> Results {
       get {
-            try {
-              resultsLock.EnterReadLock();
-              return results;
-            } finally { resultsLock.ExitReadLock(); }
+        try {
+          resultsLock.EnterReadLock();
+          return results;
+        }
+        finally { resultsLock.ExitReadLock(); }
       }
     }
@@ -97,5 +100,6 @@
                 resultsLock.EnterWriteLock();
                 this.results.Add(localJob.Id, hiveTask);
-              } finally { resultsLock.ExitWriteLock(); }
+              }
+              finally { resultsLock.ExitWriteLock(); }
             }
           });
@@ -114,4 +118,11 @@
       if (handler != null) handler(this, new EventArgs<Exception>(exception));
     }
+
+    #region IDisposable Members
+    public void Dispose() {
+      taskDownloader.ExceptionOccured -= new EventHandler<EventArgs<Exception>>(taskDownloader_ExceptionOccured);
+      resultsLock.Dispose();
+    }
+    #endregion
   }
 }
