C# 为什么我的所有事件订阅都应用于发布服务器的所有实例?

C# 为什么我的所有事件订阅都应用于发布服务器的所有实例?,c#,events,xna,C#,Events,Xna,(Aka,当我只添加了一次订阅方法时,为什么我的事件会运行2106个订阅方法副本?) 在用于向世界添加一组块(异步调用)的add方法中: 公共虚拟空添加块(IBlockCoordinate[]位置,块[]块) { 对于(int i=0;i

(Aka,当我只添加了一次订阅方法时,为什么我的事件会运行2106个订阅方法副本?)

在用于向世界添加一组块(异步调用)的add方法中:

公共虚拟空添加块(IBlockCoordinate[]位置,块[]块)
{
对于(int i=0;i
(见注释行) 那么,我只是不理解事件吗?为什么即使我只向每个块添加一次订阅,但如果我销毁任何块,它会为世界上的每个块调用一次方法?我是不是漏掉了什么明显的东西?这就好像订阅事件的方法不是特定于对象的实例,而是特定于对象本身(因此块的所有实例共享相同的事件处理程序,这对我来说不起作用)

如果我还不够清楚:上面的方法是在加载阶段异步调用的。它会在特定位置创建一组块。它将这些块中的每一个设置为在触发销毁事件时调用一个方法。然而,当我销毁任何一个块时,它调用该方法大约2000次;世界上每个街区一个

编辑:这里还有一些代码。我想这涵盖了所有关于被摧毁事件的内容

在Block.cs中:

public event EventHandler Destroyed;
    protected void OnDestroyed()
    {
        if (Destroyed != null)
        {
            Destroyed(this, null); //when the run is broken here, I can see that Destroyed has an invocationCount of ~1000-2000
        }
    }
[...]
public virtual void Damage(float amt)
    {
        health -= amt;
        if (health < 0)
            OnDestroyed(); //this line is only called once per destroyed block
    }
公共事件事件处理程序已销毁;
受保护的空OnDestroyed()
{
如果(已销毁!=null)
{
destrocted(this,null);//在这里中断运行时,我可以看到destrocted的调用计数为~1000-2000
}
}
[...]
公共虚空伤害(浮动金额)
{
健康-=amt;
如果(健康状况<0)
OnDestroyed();//每销毁一个块只调用一次此行
}
在BlockClump.cs(定义一组块的类)

公共虚拟空添加块(IBlockCoordinate[]位置,块[]块)
{
对于(int i=0;i

AddBlocks方法是在加载阶段在主游戏的一个单独线程上调用的。

结果表明,它是由不相关的代码引起的。很抱歉,在我没有探索所有选项的情况下扣动扳机问了一个问题。问题在于我的合作伙伴在编写块创建内容时使用的一些代码。为了提高效率,他在第一次创建块时缓存了所有块,并引用缓存的块来创建该类型的新块。除了没有克隆块,他只是返回了引用,所以所有的脏块实际上都是同一个实例。因此,对于我认为正在创建的每个“新”块,我都向污垢块的事件添加了一个方法

这也解释了我最近碰到的许多其他bug!所以我要解雇他。除非不是真的,因为那会使我们的室友关系紧张。而且代码来自我们实现克隆之前,所以


无论如何,谢谢大家。

您能为IBlock实现添加源代码吗。或者很难猜测发生了什么。或者,1)您多次调用事件处理程序,或者2)您多次调用AddBlocks(将多个事件处理程序添加到同一个块)。根据你发布的代码,这是不确定的。我只打了一次电话,我查过了。如果我在触发事件时中断程序并从那里开始逐步执行,我会一次又一次地执行block_destructed方法,而不会再次执行事件触发。另外,如果我在中断期间检查销毁的事件,我可以看到该事件的调用计数平均超过2000。我不认为发布块源代码会有帮助,因为唯一相关的代码是在特定条件下触发的一行事件(这只发生一次,我选中了)。我将使用我可以编辑的任何相关代码编辑主帖子
public event EventHandler Destroyed;
    protected void OnDestroyed()
    {
        if (Destroyed != null)
        {
            Destroyed(this, null); //when the run is broken here, I can see that Destroyed has an invocationCount of ~1000-2000
        }
    }
[...]
public virtual void Damage(float amt)
    {
        health -= amt;
        if (health < 0)
            OnDestroyed(); //this line is only called once per destroyed block
    }
public virtual void AddBlocks(IBlockCoordinate[] positions, Block[] blocks)
    {
        for (int i = 0; i < positions.Length; i++)
        {
            blocks[i].Coordinate = positions[i];
            blocks[i].ParentContainer = this;
            blocks[i].Destroyed += new EventHandler(block_Destroyed);
            SuperContent.Instance.debugCount++; //after all loading is finished, this static int counter reads ~2000.  That represents the number of times this code block is run for the entire game.
        }

        [... more logistics of adding blocks to the geometric model]

    }
[...]
void block_Destroyed(object sender, EventArgs e) //this function is called thousands of times with each single event fire
{
    Vector3 position = (BlockClumpCoordinate)(sender as Block).Coordinate;
    position = Vector3.Transform(position, world);
    (sender as Block).Regenerate();
    ContainingSpace.AddSpaceBlock(new SpaceBlock(   //a space block is the broken 'item' block
        (sender as Block).Clone(),
        position,
        .1f));
    components.Remove((BlockClumpCoordinate)(sender as Block).Coordinate);
}