diff --git a/common/source/java/ch/systemsx/cisd/common/concurrent/TerminableCallable.java b/common/source/java/ch/systemsx/cisd/common/concurrent/TerminableCallable.java
index abc8e2fc42f08e7969485c0911275d0ae6e9d6b8..0750382f5fcc287830b714f72d2ba5267318e62a 100644
--- a/common/source/java/ch/systemsx/cisd/common/concurrent/TerminableCallable.java
+++ b/common/source/java/ch/systemsx/cisd/common/concurrent/TerminableCallable.java
@@ -421,7 +421,7 @@ public final class TerminableCallable<V> implements Callable<V>, ITerminable
     }
 
     /**
-     * Returns <code>true</code>, if the callable is currently running and <code>false</code>
+     * Returns <code>true</code> if the callable is currently running and <code>false</code>
      * otherwise.
      */
     public boolean isRunning()
@@ -430,7 +430,15 @@ public final class TerminableCallable<V> implements Callable<V>, ITerminable
     }
 
     /**
-     * Returns <code>true</code>, if the callable has already started running.
+     * Returns <code>true</code> if the callable has been (successfully) cancelled or terminated.
+     */
+    public boolean isCancelled()
+    {
+        return threadGuard.isCancelled();
+    }
+    
+    /**
+     * Returns <code>true</code> if the callable has already started running.
      */
     public boolean hasStarted()
     {
@@ -438,7 +446,7 @@ public final class TerminableCallable<V> implements Callable<V>, ITerminable
     }
 
     /**
-     * Returns <code>true</code>, if the callable has already finished running.
+     * Returns <code>true</code> if the callable has already finished running.
      */
     public boolean hasFinished()
     {
@@ -465,12 +473,14 @@ public final class TerminableCallable<V> implements Callable<V>, ITerminable
     /**
      * Cancels the callable if it is not yet running.
      * 
+     * @param mayInterruptIfRunning If <code>true</code> and the callable is running, interrupt
+     *            its thread. Otherwise, do nothing.
      * @return <code>true</code>, if the callable is cancelled and <code>false</code>
      *         otherwise.
      */
-    public boolean cancel()
+    public boolean cancel(boolean mayInterruptIfRunning)
     {
-        return threadGuard.cancel();
+        return threadGuard.cancel(mayInterruptIfRunning);
     }
 
     /**
diff --git a/common/source/java/ch/systemsx/cisd/common/concurrent/TerminableFuture.java b/common/source/java/ch/systemsx/cisd/common/concurrent/TerminableFuture.java
index dc782131a83d1a2d2f97ff7e0895700ee372805c..ee7fea0856c129f6cbf2954324ccaa83cb8555c0 100644
--- a/common/source/java/ch/systemsx/cisd/common/concurrent/TerminableFuture.java
+++ b/common/source/java/ch/systemsx/cisd/common/concurrent/TerminableFuture.java
@@ -43,7 +43,9 @@ final class TerminableFuture<V> implements ITerminableFuture<V>
 
     public boolean cancel(boolean mayInterruptIfRunning)
     {
-        return delegateFuture.cancel(mayInterruptIfRunning);
+        final boolean canceled = delegateTerminableCallable.cancel(mayInterruptIfRunning);
+        delegateFuture.cancel(false);
+        return canceled;
     }
 
     public V get() throws InterruptedException, ExecutionException
@@ -59,7 +61,7 @@ final class TerminableFuture<V> implements ITerminableFuture<V>
 
     public boolean isCancelled()
     {
-        return delegateFuture.isCancelled();
+        return delegateTerminableCallable.isCancelled();
     }
 
     public boolean isDone()
diff --git a/common/source/java/ch/systemsx/cisd/common/concurrent/ThreadGuard.java b/common/source/java/ch/systemsx/cisd/common/concurrent/ThreadGuard.java
index 9691503906e62c56ea536baa57dd25929c5db4f9..66a32c27c5e17001e45aca33d5e4287149fde0dc 100644
--- a/common/source/java/ch/systemsx/cisd/common/concurrent/ThreadGuard.java
+++ b/common/source/java/ch/systemsx/cisd/common/concurrent/ThreadGuard.java
@@ -48,6 +48,8 @@ final class ThreadGuard
 
     private ThreadGuard.State state = State.INITIAL;
 
+    private volatile boolean cancelled = false;
+
     @SuppressWarnings("deprecation")
     private static void stopNow(Thread t)
     {
@@ -172,31 +174,43 @@ final class ThreadGuard
     }
 
     /**
-     * Returns <code>true</code>, if the guard is in state running.
+     * Returns <code>true</code> if the guard is in state <code>RUNNING</code>.
      */
     synchronized boolean isRunning()
     {
         return (state == State.RUNNING);
     }
 
+    /**
+     * Returns <code>true</code> if {@link #cancel(boolean)} has been called on the guard
+     * successfully, or when {@link #terminateAndWait(long, long)} has been called on the guard.
+     */
+    boolean isCancelled()
+    {
+        return cancelled;
+    }
+
     /**
      * Tries to cancel the guard, i.e. prevent it from running if it doesn't run yet. If canceling
      * is successful, it implies marking the guard as finished.
      * 
+     * @param mayInterruptIfRunning If <code>true</code> and the guard is in state
+     *            <code>RUNNING</code>, interrupt the thread. Otherwise, do nothing.
      * @return <code>true</code>, if the guard has been canceled successfully.
      */
-    synchronized boolean cancel()
+    synchronized boolean cancel(boolean mayInterruptIfRunning)
     {
         if (state == State.INITIAL)
         {
             state = State.CANCELED;
             // Do not call markFinished() as the stopLock is not yet initialized.
             finishedLatch.countDown();
-            return true;
+            cancelled = true;
         } else
         {
-            return false;
+            cancelled = mayInterruptIfRunning ? (tryInterruptAndGetThread() != null) : false;
         }
+        return cancelled;
     }
 
     /**
@@ -234,7 +248,7 @@ final class ThreadGuard
     boolean terminateAndWait(long waitInterruptMillis, long timeoutMillis)
             throws InterruptedException
     {
-        if (cancel())
+        if (cancel(false))
         {
             return true;
         }
@@ -242,6 +256,7 @@ final class ThreadGuard
         final Thread t = tryInterruptAndGetThread();
         if (t != null)
         {
+            cancelled = true;
             if (waitForFinished(waitInterruptMillis))
             {
                 return true;
diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/concurrent/TerminableCallableTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/concurrent/TerminableCallableTest.java
index 33093846ac7a9dc165ddc7cad92cbbf058015bfa..06da6b0151fe035fc712065095d57742b850b64c 100644
--- a/common/sourceTest/java/ch/systemsx/cisd/common/concurrent/TerminableCallableTest.java
+++ b/common/sourceTest/java/ch/systemsx/cisd/common/concurrent/TerminableCallableTest.java
@@ -160,7 +160,7 @@ public class TerminableCallableTest
                 new TestRunnable(launchLatch, milestoneLatch, Strategy.COMPLETE_IMMEDIATELY,
                         finishLatch);
         final TerminableCallable<Object> callableUnderTest = TerminableCallable.create(sensor);
-        callableUnderTest.cancel();
+        callableUnderTest.cancel(false);
         final Thread t = new Thread(callableUnderTest.asRunnable(), "cancel");
         final AtomicReference<Throwable> uncaughtException = new AtomicReference<Throwable>(null);
         t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler()