Avoid blocking game thread when saving file

I’m working on a gearvr app and trying to download an mp4 (aprox 250mb) and save it to the device.

It seems the save operation blocks the game thread, which causes the rendering to freeze for a few seconds, while the gearvr IMU remains active. The result is that the game freezes and you basically end up being able to look around a frozen quad :confused:

My download and save code is:

request->OnProcessRequestComplete().BindLambda([&](FHttpRequestPtr request, FHttpResponsePtr response, bool success) {
		if (!success) {
			return;
		}

		TArray<uint8> data = response->GetContent();
		FString path = FPaths::Combine(FPaths::GamePersistentDownloadDir(), "video.mp4");
		FBufferArchive archive;
		archive << data;

		success = FFileHelper::SaveArrayToFile(archive, *path);

		if (success) {
			UGameplayStatics::OpenLevel(GetWorld(), "Player");
		}
	});

Since the downloading operation itself does not seem to be the one blocking the UI, I assume it would be either the insertion operator archive << data or SaveArrayToFile. So I tried doing both operations on a separate thread, like so:

ACard::ACard() {
	PrimaryActorTick.bCanEverTick = true;
	
	// ...
	
	request->OnProcessRequestComplete().BindLambda([&](FHttpRequestPtr request, FHttpResponsePtr response, bool success) {
		GEngine->AddOnScreenDebugMessage(-1, 2.f,
			success ? FColor::Green : FColor::Red,
			success ? TEXT("download successful") : TEXT("download failed"));

		if (!success) {
			return;
		}

		task = Task::dispatch([response]() {
			FBufferArchive archive;
			TArray<uint8> data = response->GetContent();
			archive << data;

			FString path = FPaths::Combine(FPaths::GamePersistentDownloadDir(), "video.mp4");
			FFileHelper::SaveArrayToFile(archive, *path);
		});

		SetActorTickEnabled(true);
	});
}

void ACard::BeginPlay() {
	Super::BeginPlay();
	SetActorTickEnabled(false);
}

void ACard::Tick( float DeltaTime ) {
	Super::Tick( DeltaTime );

	if (task && task->complete) {
		SetActorTickEnabled(false);
		UGameplayStatics::OpenLevel(GetWorld(), "Player");
	}
}

Where Task is defined like so:

class  Task : public FRunnable {

private:
	TFunction<void()> task;
	FRunnableThread* thread;

public:
	bool complete{ false };

	static Task* dispatch(TFunction<void()> task) {
		auto newInstance = new Task(task);

		newInstance->thread = FRunnableThread::Create(
			newInstance,
			TEXT(""),
			0,
			TPri_BelowNormal
		);

		return newInstance;
	}

	Task(TFunction<void()> task) : task(task) {}
	bool Init() override { return true; }
	void Stop() override {}

	uint32 Run() override {
		task();
		complete = true;
		return 0;
	}
};

But the above seems to make no difference: Saving the file still blocks the UI for about 3secs.
So my question is: how should I be saving the file to storage without blocking the game itself?

UPDATE:

This issue is still not resolved. Following the advice in one of the comments below, I added logs to check that the code does indeed execute on separate threads and it does. The logs are consistent with the actions:

  1. Dispatch save task from game thread.
  2. execute task (save) in background thread.
  3. dispatch new task to load the next level from background thread.
  4. execute new task (load next level) from game thread.

Yet the UI thread still blocks.

01 - 18 19:59 : 10.404 18059 18075 D UE4 : LogTemp:Warning: Dispatch TASK : tID 18075 | is game ? 1
01 - 18 19 : 59 : 10.404 18059 18075 D UE4 : [2017.01.19 - 00.59.10:415][-8608252]LogTemp : Warning : Dispatch TASK : tID 18075 | is game ? 1
01 - 18 19 : 59 : 10.414 18059 18259 D UE4 : LogTemp:Warning: Execute TASK : tID 18259 | is game ? 0
01 - 18 19 : 59 : 10.414 18059 18075 D UE4 : [2017.01.19 - 00.59.10:419][-8608252]LogTemp : Warning : Execute TASK : tID 18259 | is game ? 0
01 - 18 19 : 59 : 10.524 18059 18140 I OVR : PhoneManagerThread - phone running!nfds = 1
01 - 18 19 : 59 : 10.524 18059 18259 D UE4 : LogTemp:Warning: Dispatch TASK : tID 18259 | is game ? 0
01 - 18 19 : 59 : 10.524 18059 18075 D UE4 : [2017.01.19 - 00.59.10:536][-8608252]LogTemp : Warning : Dispatch TASK : tID 18259 | is game ? 0
01 - 18 19 : 59 : 11.064 18059 18075 D UE4 : LogTemp:Warning: Execute TASK : tID 18075 | is game ? 1
01 - 18 19 : 59 : 11.064 18059 18075 D UE4 : [2017.01.19 - 00.59.11:072][-8608252]LogTemp : Warning : Execute TASK : tID 18075 | is game ? 1

bump. Someone, please? :frowning: