Begin/EndInvoke not synchronizing with Unity's main thread

I’m creating a networked game using tcp based sockets.
(I’m new to networking and threading stuff).

I’m using System.Net.Sockets async methods like socket.BeginReceive() and socket.EndReceive().
All the client-server connecting and messaging works. But as soon as I try access anything from a Monobehavior (so that I can actually have any effect on the Unity game), like a gameobject’s transform, an exception is thrown telling me that I can only access these properties from the main thread.

My question is why am I not back on the main thread after I call foo.EndReceive()? How do I return to the mainthread using the async socket api? Will I end up having to use the synchronous socket api and just handle the threading myself so I can properly resync with Unity’s main thread?

Thanks!

My hunch is that the problem is occurring because of the way in which i set up the beginInvoke() callbacks recursively… in that i setup the begininvoke callback inside the beginInvoke callback which perhaps isn’t executed on the mainthread??? I’m not sure… Any help would be much appreciated.

//code which sets up the callbacks which are executed when a client receives a message from the server
void BeginReceive() => _clientSocket.BeginReceive(_messageReceivedBuffer, 0, _messageReceivedBuffer.Length, SocketFlags.None, ReceiveCallback, null);

void ReceiveCallback(IAsyncResult result)
        {
            _clientSocket.EndReceive(result);

            var msg = _serializer.ByteArrayToObject<NetworkMessage>(_messageReceivedBuffer);
//this clientmanipulation manipulates the game grid and the gameobjects' which it references
//it's in this method that an exception gets thrown and the code breaks
            msg.ClientManipulation(_gameGrid); 
          
            BeginReceive();
        }

A possible solution:

Read the current thread synchronization context while you are in the main thread

SynchronizationContext mainThreadContext = SynchronizationContext.Current;

Then use it to execute your code on the main thread using its Send (synchronous execution) or Post (asynchronous execution) methods

mainThreadContext.Post(_ => Debug.Log("Hello, World!"), null);
1 Like

This is what I also do whenever I need to schedule work on the main thread. It’d be nice if Unity provided a more formal accessor for it, since at present I just cache it using a [RuntimeInitializeOnLoadMethod]-marked function.