Main thread and thread

Hello !

I’ve some question about the UE4 threading system because i got assert failed on IsInGameThread() .

I’m using a thread to Recv() data from socket, and also parsing this data etc.

Create my thread:


hProcessThread = CreateThread(NULL, 0, &MySocket::StaticThreadStart, this, 0, 0);

my recv function;


while (sess->runnable == true)
	{
		int inDataLength = recv(sock, (char*)m_recvBuffer.GetQueuePushPtr(), m_recvBuffer.GetLinearFreeSize(), 0);
		if (inDataLength > 0)
		{
			_PC_mutex.lock();
			amnt++;
			UE_LOG(LogInit, Log, TEXT("packet recv: %d"), amnt);
			ThePC->parseMyPacket(&packet);//->ParsePacket(&packet);
			popPacket(&packet);
			_PC_mutex.unlock();
		}
	}

That’s working at all, i got my packet and the parsing function work perfectly.

So here is an example:

I send login, i recv ok or not ok, then i do some thing into my playercontroller.
If my login is ok i recv my friend list and then i fill a struct and put it on a new widget:

this is exectuted in a loop and it is working if i’m not in a thread, by using thread my game crash on the get player controller.

So is any way to execute all of this inside a separate thread without getting an assert failed …?

I checked my memory adress just in case:


LogInit: This MySocket memory pointer: 0000000028CAA780
LogInit: MySocket pointer reference memory pointer PreUpdate: 0000000028CAA780
LogInit: thread MySocket memory pointer PreUpdate: 0000000028CAA780
LogInit: MySocket memory pointer player controller PreUpdate: 0000000028E71600

all the adress are ok so it’s not a segfault but a assert failed on IsInGameThread() …

Thanks for any help you can give me :).

1 Like

You cannot interact with game objects from any thread other than the main game thread. To do so, you need to queue a task to be executed in the game thread like this:



FGraphEventRef Task= FFunctionGraphTask::CreateAndDispatchWhenReady(&]()
{
	// Code placed here will run in the game thread
}, TStatId(), NULL, ENamedThreads::GameThread);

// If you want to wait for the code above to complete do this:
FTaskGraphInterface::Get().WaitUntilTaskCompletes(Task);


1 Like

It’s perfect i didn’t know that ue4 had a system to execute task like this, thank you very much :slight_smile: !!

This also was the solution for me :slight_smile:
I was wondering why my blueprintimplementable event was fine with triggering a print string node but would crash when it would call a function on a referenced player control.

There’s a slightly shorter and more readable way than the above snippet to dispatch code to the game thread, if you don’t need to get a Task object that you can wait on:



AsyncTask(ENamedThreads::GameThread, &]()
{ 
    // Code placed here will run in the game thread 
});


Also, be careful with that &] in both examples. This will cause any external variables used inside the lambda expression to be captured by reference. In many cases this will be fine, but if for example you capture a local function variable, then the reference might be invalid by the time the code is run on the game thread, leading to undefined behavior. In that case you will want to capture the variable by value, which essentially creates a copy of the variable for use inside the lambda expression.

Here’s a couple of variable capturing examples copy-pasted from Wikipedia, which explains it better than I could:



]        //no variables defined. Attempting to use any external variables in the lambda is an error.
[x, &y]   //x is captured by value, y is captured by reference
&]       //any external variable is implicitly captured by reference if used
=]       //any external variable is implicitly captured by value if used
&, x]    //x is explicitly captured by value. Other variables will be captured by reference
=, &z]   //z is explicitly captured by reference. Other variables will be captured by value


It’s also considered good practice to capture variables explicitly, rather than relying on catch-all methods like &] and =].

2 Likes