I have a Unity Android app that receive data from a server (Python script) reading data in async. The Unity main thread freeze if sometime there is no data to read, when it read data the mainthread unfreeze. I tried put NetworkStream.DataAvailable as condition and/or loop but the issue still persist.
Below the code:
void Start()
{
Client().WrapErrors();
{
async Task Client()
{
while (!IsConnected(client))
{
try
{
client = new TcpClient(host, port);
s = client.GetStream();
while (true)
{
if (s.DataAvailable)
{
Debug.Log("1 await Task.Delay(TimeSpan.FromSeconds(1.0f));");
await Task.Delay(TimeSpan.FromSeconds(1.0f));
s.ReadTimeout = 10;
Debug.Log("myCompleteMessage = (JSONNode)await ReadPacket(s);");
myCompleteMessage = (JSONNode)await ReadPacket(s);
// Other stuff after reading
}
}
}
}
}
ReadPacket
async Task<JSONNode> ReadPacket(Stream s)
{
var buffer = new byte[131072];
// Read 4 bytes (we will assume we can always read that much)
var n = s.Read(buffer, 0, 4);
if (n < 4) throw new Exception("short read");
var fileSize = BitConverter.ToUInt32(buffer, 0);
Debug.Log("Reading a blob of length" + fileSize.ToString());
// Memory stream to accumulate the reads into.
var ms = new MemoryStream();
while (ms.Length < fileSize)
{
// Figure out how much we can read -- if we're near the end,
// don't overread.
var maxRead = Math.Min(buffer.Length, fileSize - ms.Length);
var increment = await s.ReadAsync(buffer, 0, (int)maxRead);
// ... and write them into the stream.
ms.Write(buffer, 0, increment);
Debug.Log("Read" + ms.Length + "of" + fileSize);
}
Debug.Log("Loop Read ended " + fileSize);
// Decode the bytes to UTF-8 and parse.
return JSONNode.Parse(Encoding.UTF8.GetString(ms.GetBuffer()));
}
I don't know/find WrapErrors but it seems that this call makes your task run synchronous.
In such case I think you rather would use e.g.
Start()
{
Task.Run(()=> Client().WrapErrors());
}
Personal opinion: For something that is supposed to continue forever (or a while) I would rather use a proper Thread instead of a Task.
When you use Task you usually expect it to return something at some point. Also, threads can be named, which can be useful during debugging.
Finally I don't know how you are handling the results but be sure to somehow pass them back into the main thread! Most of the Unity API can only be used by the Unity main thread.