diff --git a/applications/solvers/multiphase/compressibleInterFoam/twoPhaseMixtureThermo/twoPhaseMixtureThermo.C b/applications/solvers/multiphase/compressibleInterFoam/twoPhaseMixtureThermo/twoPhaseMixtureThermo.C
index f1145196b1a184308970b0f8cccee7e5dd368303..762f487ad16937cf14dc75ae9fa0ce87efaef143 100644
--- a/applications/solvers/multiphase/compressibleInterFoam/twoPhaseMixtureThermo/twoPhaseMixtureThermo.C
+++ b/applications/solvers/multiphase/compressibleInterFoam/twoPhaseMixtureThermo/twoPhaseMixtureThermo.C
@@ -50,12 +50,6 @@ Foam::twoPhaseMixtureThermo::twoPhaseMixtureThermo
     thermo1_(nullptr),
     thermo2_(nullptr)
 {
-    // Note: we're writing files to be read in immediately afterwards.
-    //       Avoid any thread-writing problems.
-    float bufSz =
-        fileOperations::collatedFileOperation::maxThreadFileBufferSize;
-    fileOperations::collatedFileOperation::maxThreadFileBufferSize = 0;
-
     {
         volScalarField T1(IOobject::groupName("T", phase1Name()), T_);
         T1.write();
@@ -66,9 +60,9 @@ Foam::twoPhaseMixtureThermo::twoPhaseMixtureThermo
         T2.write();
     }
 
-    fileOperations::collatedFileOperation::maxThreadFileBufferSize =
-        bufSz;
-
+    // Note: we're writing files to be read in immediately afterwards.
+    //       Avoid any thread-writing problems.
+    fileHandler().flush();
 
     thermo1_ = rhoThermo::New(U.mesh(), phase1Name());
     thermo2_ = rhoThermo::New(U.mesh(), phase2Name());
diff --git a/applications/utilities/mesh/manipulation/setSet/setSet.C b/applications/utilities/mesh/manipulation/setSet/setSet.C
index 7735602a13716f7bc5c662fc3bc25513672a6f6e..bc800b920aee19d401b79881caa4a5a4d8de8e14 100644
--- a/applications/utilities/mesh/manipulation/setSet/setSet.C
+++ b/applications/utilities/mesh/manipulation/setSet/setSet.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2018 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2017-2018 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -51,7 +51,6 @@ Description
 #include "faceZoneSet.H"
 #include "pointZoneSet.H"
 #include "timeSelector.H"
-#include "collatedFileOperation.H"
 
 #include <stdio.h>
 
@@ -283,6 +282,9 @@ void removeZone
         {
             WarningInFunction << "Failed writing zone " << setName << endl;
         }
+        zones.write();
+        // Force flushing so we know it has finished writing
+        fileHandler().flush();
     }
 }
 
@@ -541,6 +543,8 @@ bool doCommand
                         << "Failed writing set "
                         << currentSet.objectPath() << endl;
                 }
+                // Make sure writing is finished
+                fileHandler().flush();
             }
         }
     }
@@ -732,8 +736,6 @@ int main(int argc, char *argv[])
     // Specific to topoSet/setSet: quite often we want to block upon writing
     // a set so we can immediately re-read it. So avoid use of threading
     // for set writing.
-    fileOperations::collatedFileOperation::maxThreadFileBufferSize = 0;
-
     timeSelector::addOptions(true, false);
     #include "addRegionOption.H"
     argList::addBoolOption("noVTK", "Do not write VTK files");
diff --git a/applications/utilities/mesh/manipulation/topoSet/topoSet.C b/applications/utilities/mesh/manipulation/topoSet/topoSet.C
index 225cd611d4aeae75c56ac1e48f71fcf667307e6e..9878b75b3c56394048cabd9d8fba4da17b6880d7 100644
--- a/applications/utilities/mesh/manipulation/topoSet/topoSet.C
+++ b/applications/utilities/mesh/manipulation/topoSet/topoSet.C
@@ -43,7 +43,6 @@ Description
 #include "faceZoneSet.H"
 #include "pointZoneSet.H"
 #include "IOdictionary.H"
-#include "collatedFileOperation.H"
 
 using namespace Foam;
 
@@ -91,6 +90,7 @@ void removeZone
         {
             WarningInFunction << "Failed writing zone " << setName << endl;
         }
+        fileHandler().flush();
     }
 }
 
@@ -199,11 +199,6 @@ polyMesh::readUpdateState meshReadUpdate(polyMesh& mesh)
 
 int main(int argc, char *argv[])
 {
-    // Specific to topoSet/setSet: quite often we want to block upon writing
-    // a set so we can immediately re-read it. So avoid use of threading
-    // for set writing.
-    fileOperations::collatedFileOperation::maxThreadFileBufferSize = 0;
-
     timeSelector::addOptions(true, false);
     #include "addDictOption.H"
     #include "addRegionOption.H"
@@ -307,6 +302,7 @@ int main(int argc, char *argv[])
                             << "Failed writing set "
                             << currentSet().objectPath() << endl;
                     }
+                    fileHandler().flush();
                 }
                 break;
 
@@ -347,6 +343,7 @@ int main(int argc, char *argv[])
                             << "Failed writing set "
                             << currentSet().objectPath() << endl;
                     }
+                    fileHandler().flush();
                 }
                 break;
 
@@ -359,6 +356,7 @@ int main(int argc, char *argv[])
                             << "Failed writing set "
                             << currentSet().objectPath() << endl;
                     }
+                    fileHandler().flush();
                 break;
 
                 case topoSetSource::INVERT:
@@ -370,6 +368,7 @@ int main(int argc, char *argv[])
                             << "Failed writing set "
                             << currentSet().objectPath() << endl;
                     }
+                    fileHandler().flush();
                 break;
 
                 case topoSetSource::REMOVE:
diff --git a/applications/utilities/parallelProcessing/decomposePar/decomposePar.C b/applications/utilities/parallelProcessing/decomposePar/decomposePar.C
index 92cbf96ba0423eefc1360d369a97a90a3c332eb3..f11942fba950439eb6b8c2b89dbf8b5f19da97d4 100644
--- a/applications/utilities/parallelProcessing/decomposePar/decomposePar.C
+++ b/applications/utilities/parallelProcessing/decomposePar/decomposePar.C
@@ -108,7 +108,6 @@ Usage
 #include "pointFieldDecomposer.H"
 #include "lagrangianFieldDecomposer.H"
 #include "decompositionModel.H"
-#include "collatedFileOperation.H"
 
 #include "faCFD.H"
 #include "emptyFaPatch.H"
@@ -523,12 +522,6 @@ int main(int argc, char *argv[])
         // Decompose the mesh
         if (!decomposeFieldsOnly)
         {
-            // Disable buffering when writing mesh since we need to read
-            // it later on when decomposing the fields
-            float bufSz =
-                fileOperations::collatedFileOperation::maxThreadFileBufferSize;
-            fileOperations::collatedFileOperation::maxThreadFileBufferSize = 0;
-
             mesh.decomposeMesh();
 
             mesh.writeDecomposition(decomposeSets);
@@ -587,8 +580,7 @@ int main(int argc, char *argv[])
                     << " for use in manual decomposition." << endl;
             }
 
-            fileOperations::collatedFileOperation::maxThreadFileBufferSize =
-                bufSz;
+            fileHandler().flush();
         }
 
 
@@ -1486,8 +1478,14 @@ int main(int argc, char *argv[])
 
                             fieldDecomposer.decomposeFields(areaScalarFields);
                             fieldDecomposer.decomposeFields(areaVectorFields);
-                            fieldDecomposer.decomposeFields(areaSphericalTensorFields);
-                            fieldDecomposer.decomposeFields(areaSymmTensorFields);
+                            fieldDecomposer.decomposeFields
+                            (
+                                areaSphericalTensorFields
+                            );
+                            fieldDecomposer.decomposeFields
+                            (
+                                areaSymmTensorFields
+                            );
                             fieldDecomposer.decomposeFields(areaTensorFields);
 
                             fieldDecomposer.decomposeFields(edgeScalarFields);
diff --git a/applications/utilities/postProcessing/graphics/PVReaders/vtkPVFoam/vtkPVFoam.C b/applications/utilities/postProcessing/graphics/PVReaders/vtkPVFoam/vtkPVFoam.C
index 3dc56dc5d0fe2e968cc69b2ca5893c6b8640566e..1cf6e69aaf718c77be7f598239d47d94d0c4a38b 100644
--- a/applications/utilities/postProcessing/graphics/PVReaders/vtkPVFoam/vtkPVFoam.C
+++ b/applications/utilities/postProcessing/graphics/PVReaders/vtkPVFoam/vtkPVFoam.C
@@ -194,7 +194,8 @@ int Foam::vtkPVFoam::setTime(const std::vector<double>& requestTimes)
 
     Time& runTime = dbPtr_();
 
-    // Get times list
+    // Get times list. Flush first to force refresh.
+    fileHandler().flush();
     instantList Times = runTime.times();
 
     int nearestIndex = timeIndex_;
@@ -301,11 +302,6 @@ Foam::vtkPVFoam::vtkPVFoam
 
     fileName FileName(vtkFileName);
 
-    // Make sure not to use the threaded version - it does not like
-    // being loaded as a shared library - static cleanup order is problematic.
-    // For now just disable the threaded writer.
-    fileOperations::collatedFileOperation::maxThreadFileBufferSize = 0;
-
     // avoid argList and get rootPath/caseName directly from the file
     fileName fullCasePath(FileName.path());
 
@@ -729,6 +725,8 @@ std::vector<double> Foam::vtkPVFoam::findTimes(const bool skipZero) const
     if (dbPtr_.valid())
     {
         const Time& runTime = dbPtr_();
+        // Get times list. Flush first to force refresh.
+        fileHandler().flush();
         instantList timeLst = runTime.times();
 
         // find the first time for which this mesh appears to exist
diff --git a/applications/utilities/postProcessing/graphics/PVReaders/vtkPVFoam/vtkPVFoamUpdateInfo.C b/applications/utilities/postProcessing/graphics/PVReaders/vtkPVFoam/vtkPVFoamUpdateInfo.C
index 26ef1d660c2db83fff233abd025d8f09203237c8..5a5b0222eaa11d7d7bdc975a2535d2cfd1389483 100644
--- a/applications/utilities/postProcessing/graphics/PVReaders/vtkPVFoam/vtkPVFoamUpdateInfo.C
+++ b/applications/utilities/postProcessing/graphics/PVReaders/vtkPVFoam/vtkPVFoamUpdateInfo.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2018 OpenFOAM Foundation
      \\/     M anipulation  | Copyright (C) 2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
@@ -225,6 +225,9 @@ void Foam::vtkPVFoam::updateInfoLagrangian
     // List of lagrangian objects across all times
     HashSet<fileName> names;
 
+    // Get times list. Flush first to force refresh.
+    fileHandler().flush();
+
     for (const instant& t : dbPtr_().times())
     {
         names.insert
@@ -697,6 +700,7 @@ void Foam::vtkPVFoam::updateInfoLagrangianFields
     // to some of the clouds.
     HashTable<wordHashSet> fields;
 
+    fileHandler().flush();
     for (const instant& t : dbPtr_().times())
     {
         for (const auto& cloudName : cloudNames)
diff --git a/src/OpenFOAM/global/fileOperations/collatedFileOperation/collatedFileOperation.C b/src/OpenFOAM/global/fileOperations/collatedFileOperation/collatedFileOperation.C
index 058ff4728ee98c349ec7e328fd6a42fe88bb8b6f..67d1985ec05ccfad6f6057370675ceaf483df212 100644
--- a/src/OpenFOAM/global/fileOperations/collatedFileOperation/collatedFileOperation.C
+++ b/src/OpenFOAM/global/fileOperations/collatedFileOperation/collatedFileOperation.C
@@ -611,6 +611,18 @@ bool Foam::fileOperations::collatedFileOperation::writeObject
     }
 }
 
+void Foam::fileOperations::collatedFileOperation::flush() const
+{
+    if (debug)
+    {
+        Pout<< "collatedFileOperation::flush : clearing and waiting for thread"
+            << endl;
+    }
+    masterUncollatedFileOperation::flush();
+    // Wait for thread to finish (note: also removes thread)
+    writer_.waitAll();
+}
+
 
 Foam::word Foam::fileOperations::collatedFileOperation::processorsDir
 (
diff --git a/src/OpenFOAM/global/fileOperations/collatedFileOperation/collatedFileOperation.H b/src/OpenFOAM/global/fileOperations/collatedFileOperation/collatedFileOperation.H
index f03e2ae43a112ea652897728ff25668d4f4e902d..f24dc52c9df501738c9ce869e53ab9c8d327372b 100644
--- a/src/OpenFOAM/global/fileOperations/collatedFileOperation/collatedFileOperation.H
+++ b/src/OpenFOAM/global/fileOperations/collatedFileOperation/collatedFileOperation.H
@@ -155,6 +155,9 @@ public:
 
         // Other
 
+            //- Forcibly wait until all output done. Flush any cached data
+            virtual void flush() const;
+
             //- Actual name of processors dir
             virtual word processorsDir(const IOobject&) const;
 
diff --git a/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.C b/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.C
index 927ca6f96c5f9103562857c35bcc91245dddcb31..7f556ae380366081c7293bd0fe16dd02c41534af 100644
--- a/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.C
+++ b/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.C
@@ -991,6 +991,17 @@ Foam::label Foam::fileOperation::nProcs
 }
 
 
+void Foam::fileOperation::flush() const
+{
+    if (debug)
+    {
+        Pout<< "fileOperation::flush : clearing processor directories cache"
+            << endl;
+    }
+    procsDirs_.clear();
+}
+
+
 Foam::fileName Foam::fileOperation::processorsCasePath
 (
     const IOobject& io,
diff --git a/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.H b/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.H
index b236e9eb45887cbdcaa99b39f4cc904fecafc79d..214ead34db443904b2496033b63afe7160910998 100644
--- a/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.H
+++ b/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.H
@@ -514,6 +514,9 @@ public:
             virtual void setTime(const Time&) const
             {}
 
+            //- Forcibly wait until all output done. Flush any cached data
+            virtual void flush() const;
+
             //- Generate path (like io.path) from root+casename with any
             //  'processorXXX' replaced by procDir (usually 'processsors')
             fileName processorsCasePath
diff --git a/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.C b/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.C
index b1d1f03130864892203f380b5a3cceca282f43b9..18ff87a6cb66d69710a6a444aa5143377c4d58c9 100644
--- a/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.C
+++ b/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.C
@@ -2561,6 +2561,13 @@ Foam::fileOperations::masterUncollatedFileOperation::NewOFstream
 }
 
 
+void Foam::fileOperations::masterUncollatedFileOperation::flush() const
+{
+    fileOperation::flush();
+    times_.clear();
+}
+
+
 Foam::label Foam::fileOperations::masterUncollatedFileOperation::addWatch
 (
     const fileName& fName
diff --git a/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.H b/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.H
index 03c100921d16b95109dddeddc1f462d88759e7e8..545f20041b7975d041400e0fe82770e58a8f4373 100644
--- a/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.H
+++ b/src/OpenFOAM/global/fileOperations/masterUncollatedFileOperation/masterUncollatedFileOperation.H
@@ -769,6 +769,9 @@ public:
             //- Callback for time change
             virtual void setTime(const Time&) const;
 
+            //- Forcibly wait until all output done. Flush any cached data
+            virtual void flush() const;
+
             //- Return cached times
             const HashPtrTable<instantList>& times() const
             {