Unity中Socket和多线程导致Editor和程序卡住解决
来源:互联网 发布:aws centos 编辑:程序博客网 时间:2024/06/09 14:57
Editor卡住的原因
Unity中使用Socket或者多线程,资源没有正确的释放导致Editor卡住。我们的项目中卡住是由于线程没有正确的关掉,TcpClient没有Close导致的。
避免Socket阻塞
在connect的时候如果连不上会等到Timeout,默认Timeout时间是20s。如果放在主循环中连,就会卡住20s。放在协程中会卡住编辑器。也就是说同步连接的时候是一定会等到Timeout的,程序或者Editor必定会卡20s。所以首先要避免连接的时候长时间阻塞。
所以最佳架构是:使用多线程和异步连接。并且消息的收发都使用队列,每个队列开个线程。发送之前检查是否连接上。
在发送队列中,使用TcpClient的异步连接:BeginConnect,然后AsyncWaitHandle.WaitOne来控制timeout。注意不管有没有连接成功,最后都要调用TcpClient.Close()关掉连接。
IAsyncResult result = client.BeginConnect(IPAddress.Parse(host), port, null, null); connected = result.AsyncWaitHandle.WaitOne(1000, false); if (connected ) { client.EndConnect(result); } else { client.Close(); }
线程要正确的退出
thread.abort()一般是无法退出线程的(abort调用了,如果thread.isAlive仍然为True就说明没有退出)。所以通常在线程的主循环中自定义控制变量isStop,需要结束的时候将isStop设置为true,退出主循环。并且需要将线程设置为守护线程(C#的isBackground,后台线程),这样主程序退出,就会自动关闭线程。
thread: while !isStop dowork
全部代码如下:
public class NetWork : MonoBehaviour { public static NetWork netWork = null; public string host = "127.0.0.1"; public int port = 10002; private TcpClient client; private bool __connected = false; public bool connected { get { return __connected; } } private NetworkStream stream; private Thread recvProcess = null, sendProcess = null; //public InputField hostText, portText; private volatile bool stopSendProcess, stopRecvProcess; //发送队列 private Queue<BaseStruct> sendQueue; //半包缓冲区 private string recvData; private int maxBufferSize = 4096; private Queue<BaseStruct> recvQueue; private void Awake() { //保证全局唯一 if (netWork != null) { DestroyImmediate(gameObject); } else { DontDestroyOnLoad(gameObject); netWork = this; } sendQueue = new Queue<BaseStruct>(); recvQueue = new Queue<BaseStruct>(); } private void Start() { netWork = this; sendProcess = new Thread(new ThreadStart(SendProcess)); sendProcess.IsBackground = true; sendProcess.Start(); stopSendProcess = false; stopRecvProcess = false; } public void TryConnect() { CreateConnection(host, port); } void CreateConnection(string host, int port) { try { client = new TcpClient(); client.NoDelay = true; //client.Connect(IPAddress.Parse(host), port); IAsyncResult result = client.BeginConnect(IPAddress.Parse(host), port, null, null); __connected = result.AsyncWaitHandle.WaitOne(1000, false); if (__connected) { client.EndConnect(result); } else { client.Close(); } } catch (SocketException ex) { __connected = false; Debug.Log("connect error: " + ex.Message); client.Close(); return; } if (__connected) { stream = client.GetStream(); if (recvProcess == null) { recvProcess = new Thread(new ThreadStart(RecvProcess)); recvProcess.IsBackground = true; recvProcess.Start(); } } } public static void WriteMessage(BaseStruct item) { if (netWork != null) netWork.Write(item); } private void Write(BaseStruct item) { sendQueue.Enqueue(item); } //数据发送线程, void SendProcess() { while (!stopSendProcess) { if (!__connected) { TryConnect(); } while (sendQueue.Count > 0 && __connected) { BaseStruct item = sendQueue.Dequeue(); byte[] buffer = System.Text.Encoding.UTF8.GetBytes(item.Serialize()); stream.Write(buffer, 0, buffer.Length); stream.Flush(); } Thread.Sleep(5); } } private void RecvProcess() { byte[] recvBuf = new byte[maxBufferSize]; while (!stopRecvProcess) { int bytesRead = stream.Read(recvBuf, 0, maxBufferSize); // 解析消息加到 recvQueue } //Debug.Log("stopRecvProcess"); } void OnApplicationQuit() { stopSendProcess = true; stopRecvProcess = true; if (__connected) { __connected = false; stream.Close(); client.Close(); } if (recvProcess != null) { //recvProcess.Abort(); // 如果没有正确关闭线程,这里的Join就会阻塞,就会卡死编辑器 // recvProcess.Join(); Debug.Log("recvProcess: " + recvProcess.IsAlive); } if (sendProcess != null) { //sendProcess.Abort(); // sendProcess.Join(); Debug.Log("sendProcess: " + sendProcess.IsAlive); } }}
阅读全文
0 0
- Unity中Socket和多线程导致Editor和程序卡住解决
- Java Swing GUI多线程之SwingUtilities.invokeLater和invokeAndWait【解决SWING界面卡住情况】
- WebApp由于需要从Spring官网下载schema文件导致启动时长时间卡住问题的分析和解决
- Unity运行时使用的程序集和Editor下不同
- Python中socket和多线程的应用
- unity中开启和关闭协同程序
- JAVA : Socket和多线程
- C#代码中解决VBA脚本导致程序代码卡住的问题
- 基于Socket和多线程编程的聊天程序实现
- 基于Java socket和多线程的简易聊天小程序
- Linux下基于socket和多线程的聊天室小程序
- 编写程序实现多次通信 (socket和多线程)
- 通过Socket和UDP实现多线程的聊天程序
- Linux下基于socket和多线程的聊天室小程序
- msysGit和TortoiseGit在push时卡住解决
- 多线程程序中,fork易导致死锁
- SharedPreference中editor.apply();和editor.commit();的区别
- Unity Editor Extensions – Handle 和Gizmos私人定制
- hdu6012Lotus and Horticulture离散化线性取最大值
- Ubuntu 16.04+OpenFace的配置和简单人脸检测
- Java并发编程:线程池的使用
- Superchaeger注册码(激活码)
- Shell 要点记录
- Unity中Socket和多线程导致Editor和程序卡住解决
- OpenGL学习——入门篇 第二章 基础实例2-3 RGBA颜色和索引色
- No sql_connection parameter is established
- 常见类---BigInteger类
- stm32 定时器 通用定时器
- 网页布局基础
- WampServer安装及切换语言
- LeetCode Merge Two Sorted Lists C++
- 实时内核简介