anchor.diff:  end;
   
   
  +procedure TKMGame.Save(const aSaveName: UnicodeString; aTimestamp: TDateTime);
  +begin
  +  Save(aSaveName, aTimestamp, fSaveWorkerThread); // Use default save worker thread
  +end;
  +
  +
   //Saves game by provided name
  -procedure TKMGame.Save(const aSaveName: UnicodeString; aTimestamp: TDateTime);
  +procedure TKMGame.Save(const aSaveName: UnicodeString; aTimestamp: TDateTime; aSaveWorkerThread: TKMWorkerThread);
   var
     fullPath, rngPath, mpLocalDataPath, newSaveName: UnicodeString;
   begin
  
positive.code: 
    //This will ensure all queued work is completed before destruction
    FreeAndNil(fSaveWorkerThread);
  
    inherited;
  end;
  
negative.code:     begin
        //Game was saved from replay (.bas file)
        if FileExists(fLoadFromFile) then
          KMCopyFileAsync(fLoadFromFile, newSaveName, True, aSaveWorkerThread);
      end else
        //Normally saved game
        {$IFDEF PARALLEL_RUNNER}
          KMCopyFileAsync(SaveName('basesave_thread_' + IntToStr(THREAD_NUMBER), EXT_SAVE_BASE, fParams.IsMultiplayer), NewSaveName, True, fSaveWorkerThread);
        {$ELSE}
          KMCopyFileAsync(SaveName('basesave', EXT_SAVE_BASE, fParams.IsMultiplayer), newSaveName, True, aSaveWorkerThread);
        {$ENDIF}
  
      // Save replay info
      fGameInputProcess.SaveToFileAsync(ChangeFileExt(fullPath, EXT_SAVE_REPLAY_DOT), aSaveWorkerThread);
  
      // Save checkpoints
      if gGameSettings.SaveCheckpoints and not SKIP_SAVE_SAVPTS_TO_FILE then
        fSavePoints.SaveToFileAsync(ChangeFileExt(fullPath, EXT_SAVE_GAME_SAVEPTS_DOT), aSaveWorkerThread);
  
      if DoSaveRandomChecks then
        try
          rngPath := ChangeFileExt(fullPath, EXT_SAVE_RNG_LOG_DOT);
          gRandomCheckLogger.SaveToPathAsync(rngPath, aSaveWorkerThread);
        except
          on E: Exception do
            gLog.AddTime('Error saving random checks to ' + rngPath); //Silently log error, don't propagate error further
  