cancel
Showing results for 
Search instead for 
Did you mean: 

How to avoid blocking UI when saving large file to storage in GearVR and Unreal.

saldavonschwart
Explorer
I'm working on a GearVR app in UE4 (4.14.1 as of now). In the app, I download a somewhat large file (a 250mb mp4) and save it to storage. While this download and save is taking place, the player should still be able to look around in the VR world and whatnot.

The issue is that once the file is done downloading and gets saved to storage, the UI freezes for about 5sec, while the GearVR IMU seems to stay responsive. The result is that the user is able to look around a frozen quad with the last rendered frame of the game.

I was originally doing download + save like this:
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("Worker"),
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 it still makes no difference and the UI still freezes when running on the device.

If running instead in the editor on desktop, there is no freeze and setting breakpoints in VS shows that the thread executing the save is indeed my worker thread. But on Android I cannot set breakpoints in VS and I can't find anywhere any documentation on at least how to get the current thread in Unreal so as to print it's name or id.

@rpalandri maybe you can help since you've been of such help already on my MSAA question?

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

   
1 REPLY 1

saldavonschwart
Explorer
Bump. Anyone has any thoughts?