FAsyncTask freezes GameThread

Hi all.
I am testing save and load game asynchronously, because if my savegame Object contains a lot of data then the main thread totally freezes for a few seconds.
The main functions are in a custom UBlueprintFunctionLibrary. They are static methods and call instances of FAutoDeleteAsyncTask and FAsyncTask.

I have used FAutoDeleteAsyncTask successfully to save the game.

//TasksFunctionLibrary.h
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "Kismet/GameplayStatics.h"
#include "SaveGameAsync.h"
#include "TasksFunctionLibrary.generated.h"
UCLASS()
class MYPROJECT2_API UTasksFunctionLibrary : public UBlueprintFunctionLibrary
{
	GENERATED_BODY() 
public:
	UFUNCTION(BlueprintCallable, Category = "SaveGame")
	static bool StartSaveGameAutoDeleteAsync(const FString& SlotName, const int UserIndex, class USaveGame* ToSave)
{
	(new FAutoDeleteAsyncTask<FSaveGameAutoDeleteAsync>(ToSave, SlotName, UserIndex))->StartBackgroundTask();
	return true;
}

//SaveGameAsync.h
#pragma once
#include "CoreMinimal.h"
#include "Async/Async.h"
#include "Kismet/GameplayStatics.h"
class MYPROJECT2_API FSaveGameAutoDeleteAsync : public FNonAbandonableTask
{
private:
	class USaveGame* saveGameInstance = nullptr;
	FString SlotName;
	int UserIndex;
public:
	friend class FAutoDeleteAsyncTask<FSaveGameAutoDeleteAsync>;

	FSaveGameAutoDeleteAsync(class USaveGame* SaveObject, const FString& SlotName, const int UserIndex): saveGameInstance(SaveObject),SlotName(SlotName),UserIndex(UserIndex){}
	~FSaveGameAutoDeleteAsync() { saveGameInstance = nullptr; }

    void DoWork()
    {
        if (saveGameInstance)
    	{
    		UGameplayStatics::SaveGameToSlot(saveGameInstance, SlotName, UserIndex);
    	}
    };

	FORCEINLINE TStatId GetStatId() const
	{
		RETURN_QUICK_DECLARE_CYCLE_STAT(FSaveGameAutoDeleteAsync, STATGROUP_ThreadPoolAsyncTasks);
	}
};

But for loading the game, I need the thread to return a savegame object to the main thread. FAutoDeleteAsyncTask destroys itself at the end and I can’t find a way to return the object. (I tried using Delegates, but it crashed).

Testing with FAsyncTask with the following code to load savegame object, the main thread is frozen:

//TasksFunctionLibrary.h
UFUNCTION(BlueprintCallable, Category = "SaveGame")
static bool LoadSaveGameAsync(const FString& SlotName, const int UserIndex, class USaveGame*& Instance)
{
	FAsyncTask<FLoadGameAsync>* MyTask = new FAsyncTask<FLoadGameAsync>(SlotName, UserIndex);
	MyTask->StartBackgroundTask();

	if (MyTask->IsWorkDone())
	{
		Instance = MyTask->GetTask().GetLoadGame();
	}

	if (MyTask->IsDone()){}
	MyTask->EnsureCompletion();

	delete MyTask;
	return true;
}

However, if I comment on IsDone and EnsureCompletion methods, the main thread does not freeze, and I can return a starting object and then delete the FAsyncTask.

//TasksFunctionLibrary.h
UFUNCTION(BlueprintCallable, Category = "SaveGame")
static bool LoadSaveGameAsync(const FString& SlotName, const int UserIndex, class USaveGame*& Instance)
{
	FAsyncTask<FLoadGameAsync>* MyTask = new FAsyncTask<FLoadGameAsync>(SlotName, UserIndex);
	MyTask->StartBackgroundTask();

	if (MyTask->IsWorkDone())
	{
		Instance = MyTask->GetTask().GetLoadGame();
	}

	/*if (MyTask->IsDone()){}
	MyTask->EnsureCompletion();*/

	delete MyTask;
	return true;
}

//SaveGameAsync.h
#pragma once
#include "CoreMinimal.h"
#include "Async/Async.h"
#include "Kismet/GameplayStatics.h"
class MYPROJECT2_API FLoadGameAsync : public FNonAbandonableTask
{
private:
	class USaveGame* saveGameInstance = nullptr;
	FString SlotName;
	int UserIndex;
public:
	friend class FAsyncTask<FLoadGameAsync>;

	FLoadGameAsync(const FString& SlotName, const int UserIndex) : SlotName(SlotName), UserIndex(UserIndex) {}
	~FLoadGameAsync() { saveGameInstance = nullptr; };

	void DoWork() { saveGameInstance = UGameplayStatics::LoadGameFromSlot(SlotName, UserIndex); }

	FORCEINLINE TStatId GetStatId() const
	{
		RETURN_QUICK_DECLARE_CYCLE_STAT(FLoadGameAsync, STATGROUP_ThreadPoolAsyncTasks);
	}

	FORCEINLINE class USaveGame* GetLoadGame() const{ return saveGameInstance; }
};

I don’t know if commenting on these two methods is safe. I don’t know if the FAsyncTask has finished when I call to delete. Any advice? Is this correct?