What you can do is a run a 0.01 timer in the game thread that watches for a global bool flag that you can set inside of the Recv func, and same raw data as well like location or type of actor to spawn (FVector, String, float, etc).
As long as you dont use pointers, you can set that simple data from ::Recv, and set the bool that you want the timer in the game thread to look for and know that the other data has now been filled.
When using simple data types only, this sort of communication between game thread and the UDP socket thread will go quite well
If your updates are happening ultra frequently, faster than 0.01 you might have issues but even something like every 0.1 seconds should give the game thread enough time to get the updates.
The game thread should set the bool back to false once it acts on the data so it knows not to run again till the other thread flips the bool again.
Rama