Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Game freezes when focusing back #82

Open
SrBrahma opened this issue May 29, 2023 · 4 comments
Open

Game freezes when focusing back #82

SrBrahma opened this issue May 29, 2023 · 4 comments

Comments

@SrBrahma
Copy link

SrBrahma commented May 29, 2023

I am using the snippet given in the README. On OnMessage, I do some complex and quite big data changes. I have ~20 messages per second.

The game works fine when it's focused, but when I alt-tab it, leave it there for some time, and go back, it gets frozen for a significant time. It seems that all the messages are queued while it's unfocused (as Update() doesn't seem to be happening) and then are processed when it gets focused again.

Anyway to fix this issue? It would be good if I could process the messages / call websocket.DispatchMessageQueue() outside the Update().

@SrBrahma
Copy link
Author

It seems that

void Awake() {
    Application.runInBackground = true;
}

helps. But, I believe it would still allow this situation under some specific circumstances. Maybe there should be a way to limit the queue / choose what to do when the queue is full?

@endel
Copy link
Owner

endel commented May 30, 2023

Hi @SrBrahma, thanks for the feedback. The raw receive loop can be found here:

public async Task Receive()
{
WebSocketCloseCode closeCode = WebSocketCloseCode.Abnormal;
await new WaitForBackgroundThread();
ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[8192]);
try
{
while (m_Socket.State == System.Net.WebSockets.WebSocketState.Open)
{
WebSocketReceiveResult result = null;
using (var ms = new MemoryStream())
{
do
{
result = await m_Socket.ReceiveAsync(buffer, m_CancellationToken);
ms.Write(buffer.Array, buffer.Offset, result.Count);
}
while (!result.EndOfMessage);
ms.Seek(0, SeekOrigin.Begin);
if (result.MessageType == WebSocketMessageType.Text)
{
lock (IncomingMessageLock)
{
m_MessageList.Add(ms.ToArray());
}
//using (var reader = new StreamReader(ms, Encoding.UTF8))
//{
// string message = reader.ReadToEnd();
// OnMessage?.Invoke(this, new MessageEventArgs(message));
//}
}
else if (result.MessageType == WebSocketMessageType.Binary)
{
lock (IncomingMessageLock)
{
m_MessageList.Add(ms.ToArray());
}
}
else if (result.MessageType == WebSocketMessageType.Close)
{
await Close();
closeCode = WebSocketHelpers.ParseCloseCodeEnum((int)result.CloseStatus);
break;
}
}
}
}
catch (Exception)
{
m_TokenSource.Cancel();
}
finally
{
await new WaitForUpdate();
OnClose?.Invoke(closeCode);
}
}

I'm not sure await new WaitForBackgroundThread() would block while the app is not focused. I believe different strategies could suit different needs in such scenario. On Colyseus, for example, every message must arrive in order to have the state synchronized properly.

Perhaps a global/static option for max queued messages could be nice.
A PR would be welcome for this! Cheers!

@SrBrahma
Copy link
Author

Sorry, I am still a beginner in C#/Unity (started less than a month ago) and i am not able to understand this or to provide a PR 😅

@SrBrahma
Copy link
Author

But, the thing is that Update(), that calls that dispatch, is only called when the app is focused. That's what GPT at least told me about the Update(), and that Application.runInBackground solution worked.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants