Unity 主线程冻结与 NetworkStream.ReadAsync? [英] Unity main thread freeze with NetworkStream.ReadAsync?

查看:23
本文介绍了Unity 主线程冻结与 NetworkStream.ReadAsync?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 Unity Android 应用程序,它从服务器(Python 脚本)接收数据,以异步方式读取数据.Unity 主线程如果有时没有要读取的数据会冻结,当它读取数据时,主线程会解冻.我尝试将 NetworkStream.DataAvailable 作为条件和/或循环,但问题仍然存在.

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.

代码下方:

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
            }
         }
      }
   }
}

读取数据包

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()));
}

推荐答案

我不知道/找不到 WrapErrors 但似乎此调用使您的任务同步运行.

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());
}


个人意见:对于应该永远持续(或一段时间)的事情,我宁愿使用适当的 Thread 而不是 Task.

当您使用 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.

最后我不知道你是如何处理结果的,但一定要以某种方式将它们传递回主线程!大多数 Unity API 只能由 Unity 主线程使用.

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.

这篇关于Unity 主线程冻结与 NetworkStream.ReadAsync?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆