Download

How can I wait for a C++ callback function finished in blueprint?

I’ll align the info about my prject and code first:
I wanna download a file from URL address, then open/read it.

I am created a C++ class inherit from UBlueprintFunctionLibrary with a BlueprintCallable static function(void UDownloadURLFile::DownloadURLFile).
Then, I add another C++ class inherit from UObject named UFileDownloadWorker, in the function UDownloadURLFile::DownloadURLFile, a local UFileDownloadWorker object will do the really download job.

There’s two function in worker:
bool Download(FString URL, FString LocalFile);
void HttpCompleteCallBack(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bSuccess);
HttpCompleteCallBack is bind in http request by using:
OnProcessRequestComplete().BindUObject(this, &UFileDownloadWorker::HttpCompleteCallBack);

Till now, the funtions works well, and after posting http request, callback function can also bring the datas back.

My question is :
After I call the BlueprintCallable function in UBlueprintFunctionLibrary, it returns immediately after post the http request.
It seems that, callback function HttpCompleteCallBack will runs in background.
Now I’m confused, How can I let the blueprint wait for the callback function finished and do the following logic?
(Just like the windows API : WaitForSingleObject)

I’ve tried to send the event by using BlueprintImplementableEvent, but I don’t know how to use it right.
Here’s my way:
Firstly, I’ve created a C++ class named UDownloadingNotice with BlueprintImplementableEvent function.
Then I add a blueprint class inherit from it.
At last, I overwrite BlueprintImplementableEvent function in blueprint.

I call the BlueprintImplementableEvent function in C++ code, but it didn’t work.
I guess that the UDownloadingNotice object created in C++ code is not exist in blueprint. but I also don’t know how to link them.
In another word, I don’t know how to use BlueprintImplementableEvent function ( how to invoke it , which class to put it in).

I will be very grateful for any comments and suggestions.

Thanks very much.

I’ve tried another way invoking event:
I’ve change my BlueprintCallable static function to a non-static one.
And I constructed it’s object in blueprint, and I also constructed a UDownloadingNotice(the class with 2 BlueprintImplementableEvent function) ,
link them in blueprint.

After I call the BlueprintImplementableEvent function in C++ code by a UDownloadingNotice(BaseClass) ptr, there’s not any response, too.

I’ve found my mistake:
The object that I’ve created in blueprint which contains 2 BlueprintImplementableEvent function is wrong.
In the blueprint node “Construct object from class”, the class type I used is BaseClass, that’s wrong.
It should be the sub class.

More problem found:

When I save file on disk. I don’t want the main thread blocked. so I created a FNonAbandonableTask, in it’s DoWork function, I do the file saving job,
Then after the file has been saved. I invoked a event in UDownloadingNotice.

The event has been received by Sub class of UDownloadingNotice created in blueprint. It works well.

but,the whole Unreal Engine Editor will crash if the event is invoked in FNonAbandonableTask::StartBackgroundTask.
If I use FNonAbandonableTask::StartSynchronousTask, it can works well. But it will made the main thread blocked when saving file.

I’ve no idea about how to wait for muti-thread event in blueprint.
I’ll keep searching and tring more ways to do that.

Any comments and suggestions is welcome.

If someone has met the same problem like mine. I hope the way I’ve tried is helpful.

Thanks.

I realized that I can provide more info.

Here’s the first line of my crash info:
Assertion failed: IsInGameThread() || HasAnyFlags(RF_ClassDefaultObject|RF_ArchetypeObject) || IsPostLoadThreadSafe() || IsA(UClass::StaticClass()) [File:D:/Build/++UE4+Licensee/Sync/Engine/Source/Runtime/CoreUObject/Private/UObject/Obj.cpp] [Line: 1037]

I’ve not enough knowledge to finger out the root cause, the only thing I can confirm is the c++ classes contains my blueprint function is all non-static, my blueprint function is also non-static. I constructed a object in blueprint then call it’s member function.

AsyncTask node you can probably find some examples online.

Thanks, I can keep searching more demos .
I think the way I use AsyncTask may be has something wrong.
I also guess that if I try more ways (such as FRunnable task or native std::thread) , it will be more clearly to solve the problem.
I’ll keep working on it for now. If there’s something new I’ve found, I’ll post it here.

Thanks for your advise.
It seems that I’ve found a way to solve the problem.

Keep invoking the event in background task. but instead invoke the event directly, I use:

AsyncTask(ENamedThreads::GameThread,
=]()-> void { EventsPtr->OnLocalFileSaved(); }
);

to post the code to GameThread.
It works for now. and I’ll do more testing to impove the performance.

Posting logic with AsyncTask can work normally on windows platform. After using it in Microsoft HoloLens 2 , it crash again. I have a new problem to solve now. : (