[尝试在事件函数中分配值时挂起
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[尝试在事件函数中分配值时挂起相关的知识,希望对你有一定的参考价值。
我正在创建必须与服务器通信的多人游戏。为了进行通信,我制作了一个ClientObject,它不断等待来自服务器的消息。接收到消息后,它将解密消息内容并与该消息一起发送事件。在广播事件时触发的函数中,我尝试将部分消息分配给PlayerObject。例如,其他玩家的名字。我的问题是,当到达Players [i] .Name = name [i]时,程序挂起。调试显示name [i]是期望值。 Player [i] .Name在分配时为null,但它是可用的String变量,因此该行应该有效。
客户端对象:
public class ClientObject
{
public Socket clientSocket;
public void Connect()
{
IPEndPoint serverAddress = new IPEndPoint(IPAddress.Parse("192.168.56.1"), 3000);
clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
clientSocket.Connect(serverAddress);
Thread thread = new Thread(new ThreadStart(ReceiveMessage));
thread.Start();
}
public void ReceiveMessage() {
try
{
while (true)
{
byte[] rcvLenBytes = new byte[4];
clientSocket.Receive(rcvLenBytes);
int rcvLen = System.BitConverter.ToInt32(rcvLenBytes, 0);
byte[] rcvBytes = new byte[rcvLen];
clientSocket.Receive(rcvBytes);
String rcv = System.Text.Encoding.ASCII.GetString(rcvBytes);
MessageReceivedEventArgs args = new MessageReceivedEventArgs();
args.Message = rcv;
if (TestMessageRecevied != null)
{
TestMessageRecevied(this, args);
}
}
}
catch
{
}
}
public delegate void MessageHandler(object sender, MessageReceivedEventArgs e);
public event MessageHandler TestMessageRecevied;
}
public class MessageReceivedEventArgs : EventArgs
{
public string Message { get; set; }
}
播放器对象:
public class PlayerObject
{
public string Name
{
get;
set;
}
public bool ReadyState
{
get;
set;
}
public int DiceLeft
{
get;
set;
}
}
就绪菜单:
在这种情况下,我分配了一个PlayerObject.Name变量,但是如果我尝试更改图像精灵或UI中文本对象的值,它也会挂起。因此,分配似乎是一个问题,但无法锻炼。如果我在Start()方法中进行赋值,则可以正常工作。
public class ReadyMenu : MonoBehaviour
{
ClientObject client;
public GameObject backgroundPanel;
public Sprite tick;
public Sprite cross;
Text pName;
Image imgCheck;
PlayerObject[] players;
// Start is called before the first frame update
void Start()
{
pName = GameObject.Find("PlayerPanel1/Name").GetComponent<Text>();
players = new PlayerObject[6];
client = new ClientObject();
client.TestMessageRecevied += Client_MessagedReceived;
client.Connect();
SendClientMessage(PlayerPrefs.GetString("name"));
}
private void Client_MessagedReceived(object sender, MessageReceivedEventArgs e)
{
Debug.Log("In C_MR: " + e.Message);
string message = e.Message;
if (message.Contains("READY"))
{
//NOT IMPLEMENTED YET
return;
}
if (message.Contains("PLAYERS"))
{
//Message before split
Debug.Log(message);
message = message.Substring(7);
//Cut PLAYERS from the string
Debug.Log("substring: "+message);
//Seperate names
char[] sep = { ' ' };
String[] names = message.Split(sep,StringSplitOptions.RemoveEmptyEntries);
Debug.Log("after name split");
Debug.Log("names length is: "+names.Length);
Debug.Log("names 0 is: "+names[0]);
for (int i = 0; i < names.Length; i++)
{
Debug.Log("in loop, i = "+i);
Debug.Log("in loop, setting playerobject name");
players[i] = new PlayerObject();
players[i].Name = names[i];
Debug.Log("in loop, after setting playerobject name");
//GameObject panel = GameObject.Find("PlayerPanel" + (i + 1));
//Debug.Log("in loop, activate apnel");
//panel.SetActive(true);
}
Debug.Log("finsihed");
}
}
名称为test的输出
在C_MR中:PLAYERStest
PLAYERtest
子字符串:测试
分割后
名称长度为:1
名称0是:测试
循环中,i = 0
循环中,设置播放器对象名称
您的问题源于您实际上并没有用players
填充PlayerObject
数组的事实。只做PlayerObject[] players = new PlayerObject[6]
您只是在创建一个包含六个空对象的数组。
因此,当您尝试访问player.Name
属性时,您正在尝试对空对象进行访问。这应该抛出一个NullReferenceException
,但是您正在Client_MessagedReceived
函数中的异步上下文中工作,并且异常似乎并不总是可悲地找到回到主线程的方式。
因此,您只需要用players
填充PlayerObject
数组,就可以了。您可以在设置名称(即players[i] = new PlayerObject()
)之前执行此操作,只要名称更改在应用程序生存期内仅发生一次,或者在创建players
数组时执行即可。
以上是关于[尝试在事件函数中分配值时挂起的主要内容,如果未能解决你的问题,请参考以下文章
AWS Lambda Snowflake Python 连接器在尝试连接时挂起
boost::interprocess 共享内存段函数 find() 如果段已经存在,则在启动时挂起
smtpclient.send 在尝试通过 Office 365 发送电子邮件时挂起