【问题标题】:C# Server: NullReferenceException right after null check [duplicate]C#服务器:空检查后立即出现 NullReferenceException [重复]
【发布时间】:2017-01-17 00:03:42
【问题描述】:

编辑:这不是重复的,我知道 NullReferenceException 是什么意思。

以下代码在空检查后立即为“目标”提供 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);

唯一设置“目标”的地方:

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被其他线程变异了?鉴于它不会一直发生,这听起来确实像是一种竞争条件。
  • 什么是无效,消息?
  • 处理多个线程/请求可能是个问题。我猜使用锁会更安全。
  • 实体不为空吗?

标签: c# server nullreferenceexception


【解决方案1】:

您的问题似乎是在 target 字段周围缺少锁定或同步。

正如你所说,当接收到数据包时,它会在多个线程上调用,那么你可以使用lock 来保护对它的访问,无论何时读取和写入它。或者,您更有可能不打算共享此类的实例和其中的其他字段,因此您可能需要考虑更改这些实例的生命周期。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-09
    • 2020-08-22
    • 1970-01-01
    相关资源
    最近更新 更多