C# 服务器:NullReferenceException 就在空检查之后
C# Server: NullReferenceException right after null check
编辑:这不是重复的,我知道 NullReferenceException 是什么意思。
以下代码在 null 检查后立即为 "target" 提供 NullReferenceException:
private Entity target;
private float newPathTimer;
private float attackTimer;
public override void Update(float deltaTime) {
attackTimer += deltaTime;
// Check for target
if (target != null) {
float distance = MathExtra.PointDistance(Entity.X, Entity.Y, target.X, target.Y);
唯一设置"target"的地方:
public override void Receive(ICommand message) {
if (message is Attack) {
target = SystemMessager.SendQuery<Entity>(new GetEntity(((Attack)message).entityID));
newPathTimer = NEW_PATH_RATE;
}
if (message is FollowPath) {
if (!((FollowPath)message).pursuit) {
target = null;
}
}
}
对"target"的所有引用:
如果有什么不同的话,这个应用程序是一个服务器,可以接收和发送数据包给客户端。
此外,我不知道如何重现此错误,它不会一直发生。
编辑:每次接收到特定数据包时都会调用接收方法。我认为数据包可能是在单独的线程上接收的,导致了这个问题。
您的问题似乎是 target
字段周围缺少锁定或同步。
正如您所说,当收到数据包时,这是在多个线程上调用的,那么您可以使用 lock
来保护对它的访问,无论何时读取和写入它。或者,您更有可能不打算共享此 class 的实例和其中的其他字段,因此您可能需要考虑更改这些实例的生命周期。
编辑:这不是重复的,我知道 NullReferenceException 是什么意思。
以下代码在 null 检查后立即为 "target" 提供 NullReferenceException:
private Entity target;
private float newPathTimer;
private float attackTimer;
public override void Update(float deltaTime) {
attackTimer += deltaTime;
// Check for target
if (target != null) {
float distance = MathExtra.PointDistance(Entity.X, Entity.Y, target.X, target.Y);
唯一设置"target"的地方:
public override void Receive(ICommand message) {
if (message is Attack) {
target = SystemMessager.SendQuery<Entity>(new GetEntity(((Attack)message).entityID));
newPathTimer = NEW_PATH_RATE;
}
if (message is FollowPath) {
if (!((FollowPath)message).pursuit) {
target = null;
}
}
}
对"target"的所有引用:
如果有什么不同的话,这个应用程序是一个服务器,可以接收和发送数据包给客户端。
此外,我不知道如何重现此错误,它不会一直发生。
编辑:每次接收到特定数据包时都会调用接收方法。我认为数据包可能是在单独的线程上接收的,导致了这个问题。
您的问题似乎是 target
字段周围缺少锁定或同步。
正如您所说,当收到数据包时,这是在多个线程上调用的,那么您可以使用 lock
来保护对它的访问,无论何时读取和写入它。或者,您更有可能不打算共享此 class 的实例和其中的其他字段,因此您可能需要考虑更改这些实例的生命周期。