Multithreading a Custom Landscape

The Problem
I’m creating a landscape using an InstancedStaticMeshComponent using noise. The calculations were taking up too much of the game thread, so I decided to put it on a separate thread. The problem seems to be that the task executes too fast and leaves gaps in my landscape.

The problem is fixed if I use an FPlatformProcess::Sleep(0.01f); but that takes forever to generate my landscape and also has the same issue if I switch windows and the framerate drops.

The Code
This is the shortened version of the class responsible for creating the landscape

class FAsyncWorldCreation : public FNonAbandonableTask
{
	friend class FAutoDeleteAsyncTask<FAsyncWorldCreation>;
public:

	DECLARE_DELEGATE_TwoParams(FAsyncGenerationCompleted, FAsyncPartitionGrid, FAsyncTileReturn)
	DECLARE_DELEGATE_TwoParams(FTileReturnCall, FTransform, int32)

	UPROPERTY()
	FAsyncGenerationCompleted OnAsyncCreateComplete;

	UPROPERTY()
	FTileReturnCall TestTileReturn;

	FAsyncWorldCreation(AWorldGenerator* InWorld, bool bNoTrees, bool bNoSeed);

	void DoWork();
	FORCEINLINE TStatId GetStatId() const { // Probably declares the Task to the TaskGraph
		RETURN_QUICK_DECLARE_CYCLE_STAT(FAsyncWorldCreation, STATGROUP_ThreadPoolAsyncTasks);
	}

private:

	UPROPERTY()
	TWeakObjectPtr<AWorldGenerator> WorldRef;

	FAsyncTileReturn AsyncGenerateWorld(FAsyncPartitionGrid& ReturnWorld);

};

And this is how I create the new Task

	AsyncTask(ENamedThreads::AnyHiPriThreadHiPriTask, [&]() 
		{
			(new FAutoDeleteAsyncTask<FAsyncWorldCreation>(this, bNoTrees, bDontGenerateSeed))->StartBackgroundTask();
		});

To generate the landscape I nest the Y loop in the X loop, and for every Y tile created I execute a delegate that adds an instance to the component. I have very little knowledge with multithreading, so I have no idea how to solve this.

The Question
How can I do the calculations on a separate thread without slowing the thread down and still have the landscape generate properly.

EDIT
After some more testing, it seems to be something with the way the delegate is executed. If I execute this after every Y tile

 AsyncTask(ENamedThreads::GameThread, [&]()
					{
						TestTileReturn.ExecuteIfBound(InstanceTransform, LandType);
						//UE_LOG(LogTemp, Warning, TEXT("X: %d, Y: %d"), xi, yi)
					});

it generates the whole world with holes in it. However, if I change the & to a = It doesn’t generate wholes, but it also doesn’t generate the whole world.

is this a thread per “pillar” or a thread per region, you will also be making a big assumption on the number of cores/threads the user will have. Take a look at the Steam Hardware survey for core count, I can’t find the tread count, and we can not presume Hyper Threading/ SMT (because of different actions taken by Intel and AMD over the years)

maybe expanding the physical size and going into bigger “chunks” can “slow it down” it can also lead to more interesting deviations (especially if there is some random offset into the noise function for a given chunk).

be aware that there is a cost of spinning up the Async in the first place (segmenting memory which could hit paging with big operations or “many” small operations), and then a cost in the main-thread being paused on the completion of the Async. Then anything dealing with “spawn” happens on the main thread in the first place.

There is one background thread for the whole world. I have optimized the calculations so it takes about 1 - 3 seconds on my intel i5. I am aware that there will be a hitch once the instances are created, but I would like to have the loading screen not freeze up for the entire time the world is being generated (especially for slower devices). As for memory I have two structs. One which holds a TArray<FBox> and a TArray<FPartitionedTiles> (FPartitionedTiles is just an array for holding tile info) and then the other for holding the tile Transforms and material switch (TArray<FTransform> and a TArray<int32>)

Anyone know how to solve this?

Can anyone show me how to run a thread in the background just like it would on the game thread?