diff --git a/Base/Progress/DelayedProgressCounter.cpp b/Base/Progress/DelayedProgressCounter.cpp
index 2e14ef5e5f2c3c171271867d10ab39adc940f483..1a97403d2e25863f3fa6c8cfe2be5c1c4e41bbff 100644
--- a/Base/Progress/DelayedProgressCounter.cpp
+++ b/Base/Progress/DelayedProgressCounter.cpp
@@ -14,12 +14,15 @@
 
 #include "Base/Progress/DelayedProgressCounter.h"
 #include "Base/Progress/ProgressHandler.h"
+#include <stdexcept>
 
-DelayedProgressCounter::DelayedProgressCounter(ProgressHandler* p_progress, size_t interval)
-    : m_progress(p_progress)
+DelayedProgressCounter::DelayedProgressCounter(ProgressHandler* progress, size_t interval)
+    : m_progress(progress)
     , m_interval(interval)
     , m_count(0)
 {
+    if (!progress->alive())
+        throw std::runtime_error("dead process (user interrupt?)");
 }
 
 void DelayedProgressCounter::stepProgress()
diff --git a/Base/Progress/DelayedProgressCounter.h b/Base/Progress/DelayedProgressCounter.h
index c7f42b9c51105ab24f8fe8857d5bea7573b11cae..ec75ed41ba3be142e05a8e7b23b28240b69ea4d3 100644
--- a/Base/Progress/DelayedProgressCounter.h
+++ b/Base/Progress/DelayedProgressCounter.h
@@ -26,7 +26,7 @@ class ProgressHandler;
 
 class DelayedProgressCounter {
 public:
-    DelayedProgressCounter(ProgressHandler* p_progress, size_t interval);
+    DelayedProgressCounter(ProgressHandler* progress, size_t interval);
     ~DelayedProgressCounter() = default;
 
     //! Increments inner counter; at regular intervals updates progress handler.
diff --git a/Sim/Computation/ComputationStatus.h b/Sim/Computation/ComputationStatus.h
deleted file mode 100644
index 396e303dc6d7fd28ab95135f994a90c07b623731..0000000000000000000000000000000000000000
--- a/Sim/Computation/ComputationStatus.h
+++ /dev/null
@@ -1,50 +0,0 @@
-//  ************************************************************************************************
-//
-//  BornAgain: simulate and fit reflection and scattering
-//
-//! @file      Sim/Computation/ComputationStatus.h
-//! @brief     Defines and implements interface class ComputationStatus.
-//!
-//! @homepage  http://www.bornagainproject.org
-//! @license   GNU General Public License v3 or higher (see COPYING)
-//! @copyright Forschungszentrum Jülich GmbH 2018
-//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
-//
-//  ************************************************************************************************
-
-#ifdef SWIG
-#error no need to expose this header to Swig
-#endif // SWIG
-#ifndef BORNAGAIN_SIM_COMPUTATION_COMPUTATIONSTATUS_H
-#define BORNAGAIN_SIM_COMPUTATION_COMPUTATIONSTATUS_H
-
-#include <string>
-
-//! Completion status (flag and text) of a numeric computation.
-
-class ComputationStatus {
-public:
-    ComputationStatus()
-        : m_status(IDLE)
-    {
-    }
-
-    bool isCompleted() const { return m_status == COMPLETED; }
-    std::string errorMessage() const { return m_error_message; }
-
-    void setRunning() { m_status = RUNNING; }
-    void setCompleted() { m_status = COMPLETED; }
-    void setFailed(const std::string& message)
-    {
-        m_error_message = message;
-        m_status = FAILED;
-    }
-
-private:
-    enum ESimulationStatus { IDLE, RUNNING, COMPLETED, FAILED };
-
-    ESimulationStatus m_status;
-    std::string m_error_message;
-};
-
-#endif // BORNAGAIN_SIM_COMPUTATION_COMPUTATIONSTATUS_H
diff --git a/Sim/Computation/DWBAComputation.cpp b/Sim/Computation/DWBAComputation.cpp
index a04acc56263e507a4a15a1740d7fb8fc7be97c3c..99d7ffe3a962c34e179e3bcdeb66b414ab075a47 100644
--- a/Sim/Computation/DWBAComputation.cpp
+++ b/Sim/Computation/DWBAComputation.cpp
@@ -43,8 +43,6 @@ DWBAComputation::~DWBAComputation() = default;
 void DWBAComputation::runProtected()
 {
     for (auto it = m_begin_it; it != m_end_it; ++it) {
-        if (!m_progress->alive())
-            break;
         DiffuseElement& ele = *it;
 
         const Fluxes fluxes_in = m_re_sample.fluxesIn(ele.getKi());
diff --git a/Sim/Computation/IComputation.cpp b/Sim/Computation/IComputation.cpp
index da177adccf18b8645e6bb98cb92ee958e6d5fa5a..e48a22f9faafd7ff6cd657f5bcdddc5fbc39151c 100644
--- a/Sim/Computation/IComputation.cpp
+++ b/Sim/Computation/IComputation.cpp
@@ -21,35 +21,13 @@ IComputation::IComputation(const ReSample& re_sample, const SimulationOptions& o
                            ProgressHandler& progress)
     : m_re_sample(re_sample)
     , m_options(options)
-    , m_progress(&progress)
+    , m_progress_counter(std::make_unique<DelayedProgressCounter>(&progress, 100))
 {
 }
 
 IComputation::~IComputation() = default;
 
-void IComputation::setProgressHandler(ProgressHandler* progress) const
-{
-    m_progress_counter = std::make_unique<DelayedProgressCounter>(progress, 100);
-}
-
 void IComputation::stepProgress() const
 {
-    if (m_progress_counter)
-        m_progress_counter->stepProgress();
-}
-
-void IComputation::compute()
-{
-    m_status.setRunning();
-    try {
-        if (!m_progress->alive())
-            return;
-        setProgressHandler(m_progress);
-
-        runProtected(); // <--- here the main work is done
-
-        m_status.setCompleted();
-    } catch (const std::exception& ex) {
-        m_status.setFailed(ex.what());
-    }
+    m_progress_counter->stepProgress();
 }
diff --git a/Sim/Computation/IComputation.h b/Sim/Computation/IComputation.h
index 448e9aa714232938f7817fd0a5d567934c5543fe..be27585d4c57bf434611f9a7ca3f8058195019e7 100644
--- a/Sim/Computation/IComputation.h
+++ b/Sim/Computation/IComputation.h
@@ -18,11 +18,9 @@
 #ifndef BORNAGAIN_SIM_COMPUTATION_ICOMPUTATION_H
 #define BORNAGAIN_SIM_COMPUTATION_ICOMPUTATION_H
 
-#include "Sim/Computation/ComputationStatus.h"
 #include <memory>
 
 class DelayedProgressCounter;
-class MultiLayer;
 class ReSample;
 class ProgressHandler;
 class SimulationOptions;
@@ -38,26 +36,17 @@ public:
                  ProgressHandler& progress);
     virtual ~IComputation();
 
-    //! Calls runProtected(), catches exceptions, sets m_status.
-    void compute();
-
-    bool isCompleted() const { return m_status.isCompleted(); }
-    std::string errorMessage() const { return m_status.errorMessage(); }
+    //! Runs computation. May throw.
+    virtual void runProtected() = 0;
 
 protected:
-    void setProgressHandler(ProgressHandler* progress) const;
     void stepProgress() const;
 
     const ReSample& m_re_sample;
     const SimulationOptions& m_options;
-    ProgressHandler* m_progress;
 
 private:
-    //! Runs computation. May throw. To be called from runProtected(), which catches exceptions.
-    virtual void runProtected() = 0;
-
     mutable std::unique_ptr<DelayedProgressCounter> m_progress_counter;
-    ComputationStatus m_status;
 };
 
 #endif // BORNAGAIN_SIM_COMPUTATION_ICOMPUTATION_H
diff --git a/Sim/Simulation/ISimulation.cpp b/Sim/Simulation/ISimulation.cpp
index 904f9b287e8941fd4951d41a008dc1c322cc62c1..1809d28eb0fc6ce515899aa051a56f5c4746c3b0 100644
--- a/Sim/Simulation/ISimulation.cpp
+++ b/Sim/Simulation/ISimulation.cpp
@@ -25,6 +25,7 @@
 #include "Sim/Computation/IComputation.h"
 #include <gsl/gsl_errno.h>
 #include <iostream>
+#include <mutex>
 #include <thread>
 
 namespace {
@@ -130,7 +131,7 @@ SimulationResult ISimulation::simulate()
 
     prepareSimulation();
 
-    const auto re_sample = ReSample::make(*m_sample, options(), force_polarized());
+    const ReSample re_sample = ReSample::make(*m_sample, options(), force_polarized());
 
     const size_t total_size = numberOfElements();
     size_t param_combinations = distributionHandler().getTotalNumberOfSamples();
@@ -217,41 +218,44 @@ void ISimulation::runSingleSimulation(const ReSample& re_sample, size_t batch_st
 
     if (n_threads == 1) {
         // Run computation in current thread.
-        const auto& c = createComputation(re_sample, batch_start, batch_size);
-        c->compute(); // <---- here most work is done (unthreaded case)!
-        if (!c->isCompleted())
-            throw std::runtime_error("Unexpected error in simulation:\n" + c->errorMessage());
+        try {
+            const auto& c = createComputation(re_sample, batch_start, batch_size);
+            c->runProtected(); // <---- here most work is done (unthreaded case)!
+        } catch (const std::exception& ex) {
+            throw std::runtime_error(std::string("Unexpected error in simulation:\n") + ex.what());
+        }
 
     } else {
-        // Create batch computations.
-        std::vector<std::unique_ptr<IComputation>> computations;
+        // Launch computation threads.
+        std::vector<std::unique_ptr<std::thread>> threads;
+        std::vector<std::string> failure_messages;
+        std::mutex mutex;
         for (size_t i_thread = 0; i_thread < n_threads; ++i_thread) {
             const size_t thread_start = batch_start + startIndex(n_threads, i_thread, batch_size);
             const size_t thread_size = batchSize(n_threads, i_thread, batch_size);
             if (thread_size == 0)
                 break;
-            computations.emplace_back(createComputation(re_sample, thread_start, thread_size));
+            threads.emplace_back(new std::thread(
+                [this, &re_sample, &failure_messages, &mutex, thread_start, thread_size]() {
+                    try {
+                        const auto& c = createComputation(re_sample, thread_start, thread_size);
+                        c->runProtected(); // <---- here most work is done (threaded case)!
+                    } catch (const std::exception& ex) {
+                        mutex.lock();
+                        failure_messages.push_back(ex.what());
+                        mutex.unlock();
+                    }
+                }));
         }
 
-        // Run computations in several threads.
-        std::vector<std::unique_ptr<std::thread>> threads;
-        for (const auto& c : computations)
-            threads.emplace_back(new std::thread([&c]() {
-                c->compute(); // <---- here most work is done (threaded case)!
-            }));
-
         // Wait for threads to complete.
         for (auto& thread : threads)
             thread->join();
 
         // Check successful completion.
-        std::vector<std::string> failure_messages;
-        for (const auto& c : computations)
-            if (!c->isCompleted())
-                failure_messages.push_back(c->errorMessage());
         if (!failure_messages.empty())
-            throw std::runtime_error("Unexpected error in simulation thread(s):\n"
-                                     + BaseUtils::String::join(failure_messages, " --- "));
+            throw std::runtime_error("Unexpected error(s) in simulation thread(s):\n"
+                                     + BaseUtils::String::join(failure_messages, "\n"));
     }
 
     normalize(batch_start, batch_size);