Index: trunk/sources/HeuristicLab.Grid/ClientForm.cs
===================================================================
--- trunk/sources/HeuristicLab.Grid/ClientForm.cs	(revision 30)
+++ trunk/sources/HeuristicLab.Grid/ClientForm.cs	(revision 32)
@@ -34,11 +34,16 @@
 using System.IO;
 using System.IO.Compression;
+using System.Net;
 
 namespace HeuristicLab.Grid {
-  public partial class ClientForm : Form {
-
+  [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext = false)]
+  public partial class ClientForm : Form, IClient {
     private ChannelFactory<IEngineStore> factory;
+    private ServiceHost clientHost;
     private System.Timers.Timer fetchOperationTimer;
     private IEngineStore engineStore;
+    private Guid currentGuid;
+    private ProcessingEngine currentEngine;
+    private string clientUrl;
 
     public ClientForm() {
@@ -48,7 +53,10 @@
       fetchOperationTimer.Elapsed += new System.Timers.ElapsedEventHandler(fetchOperationTimer_Elapsed);
       statusTextBox.Text = "Stopped";
+      currentGuid = Guid.Empty;
     }
 
     private void startButton_Click(object sender, EventArgs e) {
+      clientUrl = "net.tcp://" + Dns.GetHostAddresses(Dns.GetHostName())[0] + ":8002/Grid/Client";
+      clientHost = new ServiceHost(this, new Uri(clientUrl));
       try {
         NetTcpBinding binding = new NetTcpBinding();
@@ -56,5 +64,9 @@
         binding.ReaderQuotas.MaxStringContentLength = 100000000; // also 100M chars
         binding.ReaderQuotas.MaxArrayLength = 100000000; // also 100M elements;
-        binding.Security.Mode = SecurityMode.None;        
+        binding.Security.Mode = SecurityMode.None;
+
+        clientHost.AddServiceEndpoint(typeof(IClient), binding, clientUrl);
+        clientHost.Open();
+
         factory = new ChannelFactory<IEngineStore>(binding);
         engineStore = factory.CreateChannel(new EndpointAddress(addressTextBox.Text));
@@ -65,6 +77,7 @@
         statusTextBox.Text = "Waiting for engine";
 
-      } catch (Exception ex) {
+      } catch (CommunicationException ex) {
         MessageBox.Show("Exception while connecting to the server: " + ex.Message);
+        clientHost.Abort();
         startButton.Enabled = true;
         stopButton.Enabled = false;
@@ -76,4 +89,5 @@
       fetchOperationTimer.Stop();
       factory.Abort();
+      clientHost.Close();
       statusTextBox.Text = "Stopped";
       stopButton.Enabled = false;
@@ -83,16 +97,17 @@
     private void fetchOperationTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
       byte[] engineXml;
-      Guid guid;
       fetchOperationTimer.Stop();
-      if (engineStore.TryTakeEngine(out guid, out engineXml)) {
-        ProcessingEngine engine = RestoreEngine(engineXml);
+      if (engineStore.TryTakeEngine(clientUrl, out currentGuid, out engineXml)) {
+        currentEngine = RestoreEngine(engineXml);
         if (InvokeRequired) { Invoke((MethodInvoker)delegate() { statusTextBox.Text = "Executing engine"; }); } else statusTextBox.Text = "Executing engine";
-        engine.Finished += delegate(object src, EventArgs args) {
-          byte[] resultScopeXml = SaveScope(engine.InitialOperation.Scope);
-          engineStore.StoreResult(guid, resultScopeXml);
+        currentEngine.Finished += delegate(object src, EventArgs args) {
+          byte[] resultScopeXml = SaveScope(currentEngine.InitialOperation.Scope);
+          engineStore.StoreResult(currentGuid, resultScopeXml);
+          currentGuid = Guid.Empty;
+          currentEngine = null;
           fetchOperationTimer.Interval = 100;
           fetchOperationTimer.Start();
         };
-        engine.Execute();
+        currentEngine.Execute();
       } else {
         if(InvokeRequired) { Invoke((MethodInvoker)delegate() { statusTextBox.Text = "Waiting for engine"; }); } else statusTextBox.Text = "Waiting for engine";
@@ -100,4 +115,11 @@
         fetchOperationTimer.Start();
       }
+    }
+    public void Abort(Guid guid) {
+      if(!IsRunningEngine(guid)) return;
+      currentEngine.Abort();
+    }
+    public bool IsRunningEngine(Guid guid) {
+      return currentGuid == guid;
     }
     private ProcessingEngine RestoreEngine(byte[] engine) {
Index: trunk/sources/HeuristicLab.Grid/EngineStore.cs
===================================================================
--- trunk/sources/HeuristicLab.Grid/EngineStore.cs	(revision 30)
+++ trunk/sources/HeuristicLab.Grid/EngineStore.cs	(revision 32)
@@ -27,5 +27,5 @@
 
 namespace HeuristicLab.Grid {
-  [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext=false)]
+  [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext = false)]
   public class EngineStore : IEngineStore {
     private Queue<Guid> engineQueue;
@@ -33,5 +33,7 @@
     private Dictionary<Guid, byte[]> runningEngines;
     private Dictionary<Guid, byte[]> results;
+    private Dictionary<Guid, string> runningClients;
     private object bigLock;
+    private ChannelFactory<IClient> clientChannelFactory;
 
     private event EventHandler ResultRecieved;
@@ -59,11 +61,20 @@
       waitingEngines = new Dictionary<Guid, byte[]>();
       runningEngines = new Dictionary<Guid, byte[]>();
+      runningClients = new Dictionary<Guid, string>();
       results = new Dictionary<Guid, byte[]>();
       bigLock = new object();
+
+      NetTcpBinding binding = new NetTcpBinding();
+      binding.MaxReceivedMessageSize = 100000000; // 100Mbytes
+      binding.ReaderQuotas.MaxStringContentLength = 100000000; // also 100M chars
+      binding.ReaderQuotas.MaxArrayLength = 100000000; // also 100M elements;
+      binding.Security.Mode = SecurityMode.None;
+
+      clientChannelFactory = new ChannelFactory<IClient>(binding);
     }
 
-    public bool TryTakeEngine(out Guid guid, out byte[] engine) {
-      lock (bigLock) {
-        if (engineQueue.Count == 0) {
+    public bool TryTakeEngine(string clientUrl, out Guid guid, out byte[] engine) {
+      lock(bigLock) {
+        if(engineQueue.Count == 0) {
           guid = Guid.Empty;
           engine = null;
@@ -74,4 +85,5 @@
           waitingEngines.Remove(guid);
           runningEngines[guid] = engine;
+          runningClients[guid] = clientUrl;
           return true;
         }
@@ -80,8 +92,9 @@
 
     public void StoreResult(Guid guid, byte[] result) {
-      lock (bigLock) {
-        if (!runningEngines.ContainsKey(guid)) return; // ignore result when the engine is not known to be running
+      lock(bigLock) {
+        if(!runningEngines.ContainsKey(guid)) return; // ignore result when the engine is not known to be running
 
         runningEngines.Remove(guid);
+        runningClients.Remove(guid);
         results[guid] = result;
         OnResultRecieved(guid);
@@ -90,5 +103,5 @@
 
     internal void AddEngine(Guid guid, byte[] engine) {
-      lock (bigLock) {
+      lock(bigLock) {
         engineQueue.Enqueue(guid);
         waitingEngines.Add(guid, engine);
@@ -97,5 +110,5 @@
 
     internal byte[] RemoveResult(Guid guid) {
-      lock (bigLock) {
+      lock(bigLock) {
         byte[] result = results[guid];
         results.Remove(guid);
@@ -106,6 +119,6 @@
     internal byte[] GetResult(Guid guid) {
       ManualResetEvent waitHandle = new ManualResetEvent(false);
-      lock (bigLock) {
-        if (results.ContainsKey(guid)) {
+      lock(bigLock) {
+        if(results.ContainsKey(guid)) {
           byte[] result = results[guid];
           results.Remove(guid);
@@ -114,5 +127,5 @@
           ResultRecieved += delegate(object source, EventArgs args) {
             ResultRecievedEventArgs resultArgs = (ResultRecievedEventArgs)args;
-            if (resultArgs.resultGuid == guid) {
+            if(resultArgs.resultGuid == guid) {
               waitHandle.Set();
             }
@@ -124,5 +137,5 @@
       waitHandle.Close();
 
-      lock (bigLock) {
+      lock(bigLock) {
         byte[] result = results[guid];
         results.Remove(guid);
@@ -131,8 +144,22 @@
     }
 
+    internal void AbortEngine(Guid guid) {
+      string clientUrl = "";
+      lock(bigLock) {
+        if(runningClients.ContainsKey(guid)) {
+          clientUrl = runningClients[guid];
+        }
+
+        if(clientUrl != "") {
+          IClient client = clientChannelFactory.CreateChannel(new EndpointAddress(clientUrl));
+          client.Abort(guid);
+        }
+      }
+    }
+
     private void OnResultRecieved(Guid guid) {
       ResultRecievedEventArgs args = new ResultRecievedEventArgs();
       args.resultGuid = guid;
-      if (ResultRecieved != null) {
+      if(ResultRecieved != null) {
         ResultRecieved(this, args);
       }
Index: trunk/sources/HeuristicLab.Grid/GridServer.cs
===================================================================
--- trunk/sources/HeuristicLab.Grid/GridServer.cs	(revision 30)
+++ trunk/sources/HeuristicLab.Grid/GridServer.cs	(revision 32)
@@ -46,5 +46,5 @@
 
     public void AbortEngine(Guid engine) {
-      throw new NotImplementedException();
+      engineStore.AbortEngine(engine);
     }
   }
Index: trunk/sources/HeuristicLab.Grid/HeuristicLab.Grid.csproj
===================================================================
--- trunk/sources/HeuristicLab.Grid/HeuristicLab.Grid.csproj	(revision 30)
+++ trunk/sources/HeuristicLab.Grid/HeuristicLab.Grid.csproj	(revision 32)
@@ -63,4 +63,5 @@
     <Compile Include="GridServerApplication.cs" />
     <Compile Include="HeuristicLabGridPlugin.cs" />
+    <Compile Include="IClient.cs" />
     <Compile Include="IEngineStore.cs" />
     <Compile Include="IGridServer.cs" />
Index: trunk/sources/HeuristicLab.Grid/IClient.cs
===================================================================
--- trunk/sources/HeuristicLab.Grid/IClient.cs	(revision 32)
+++ trunk/sources/HeuristicLab.Grid/IClient.cs	(revision 32)
@@ -0,0 +1,16 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.ServiceModel;
+
+namespace HeuristicLab.Grid {
+  [ServiceContract(Namespace = "http://HeuristicLab.Grid")]
+  interface IClient {
+    [OperationContract]
+    void Abort(Guid guid);
+
+    [OperationContract]
+    bool IsRunningEngine(Guid guid);
+  }
+}
Index: trunk/sources/HeuristicLab.Grid/IEngineStore.cs
===================================================================
--- trunk/sources/HeuristicLab.Grid/IEngineStore.cs	(revision 30)
+++ trunk/sources/HeuristicLab.Grid/IEngineStore.cs	(revision 32)
@@ -29,7 +29,6 @@
   [ServiceContract(Namespace = "http://HeuristicLab.Grid")]
   interface IEngineStore {
-
     [OperationContract]
-    bool TryTakeEngine(out Guid guid, out byte[] engine);
+    bool TryTakeEngine(string clientUrl, out Guid guid, out byte[] engine);
 
     [OperationContract]
