I’m trying to implement a WebSockets client that waits for data from a server and posts the data to the game as soon as it becomes available. Since I don’t want to rely on the game’s Tick frequency, I wanted to make the WebSocket client a FRunnable subclass and start the listener as a thread. Since it doesn’t seem to be possible to extend the UIObject or AActor class as FRunnable subclass, I start my thread in my module’s StartupModule() function, making the client listen from the moment the module is loaded.
This seems to work and I am able to receive data and display the data in the game. However, I would like to have a Blueprint event fired at the moment the data becomes available, so I can make other objects act on this data. The issue seems to be that the FRunnable subclass can not be defined as a UCLASS and the WebSockets callback function is a static function. The DECLARE_EVENT and DECLARE_DELEGATE macros all rersult in non-static objects that can not be called from within a static function. Is there any way I can fire a Blueprint event from within a static function in a FRunnable class?
If you are trying to fire an BP event from within the FRunnables event loop (the while within the Run function) it won’t work, to fire a BP event you should be on the same thread as the BP execution. I have a similar setting for some of my editor tools where I listen to a socket on a FRunnable and then push the received data onto a processing queue that is written in your FRunnable thread and read from the game thread where BP execution is present.
You could read the content from the queue for example within a tick function of a special actor or object like a custom UEngine instance or your GameMode. This strategy is called Producer-Consumer-Problem, a good thing about doing it that way is that you can handle how many events are being fired per tick.
An example of such a queue is the deferred command queue of UEngine, it is used to issue commands from other threads which are executed on the main thread:
Thanks for your quick answer! The only thing I was wondering with a solution like this is concurrency. Wouldn’t events fired in Blueprint be asynchronous with the engine ticks, allowing data to be received at it’s own pace? When polling data using the ticks, the data can only arrive in sync with the engine loop. It would be nice if the data can be processed as soon as it arrives.
That would be nice but you have to send the data from your thread to the main thread where blueprint is running, the safest way in doing this without using locks and synchronization primitives is using a queue.