订阅事件由于空引用而未触发

时间:2013-05-08 08:33:12

标签: c#

我在toPickedImage方法中得到null引用错误,我不明白为什么会这样。任何人都可以帮我解释为什么我会收到这个错误。

任何和所有帮助将不胜感激!

代码如下:

public partial class ownGUI : UserControl
{
    private string m_id;
    private int m_value;

    public event EventHandler<GameEventArgs> Pickedimage;

    public ownGUI()
    {
        InitializeComponent();
    }

    public ownGUI(String id, int value)
    {
        InitializeComponent();
        m_id = id;
        m_value = value;            
        GameEventArgs image = new GameEventArgs(m_id, m_value);
        toPickedimage(image);       

    }

    public void toPickedimage(GameEventArgs e)
    {
        if (Pickedimage != null) 
        {
            Pickedimage(this, e);
        }
    }
}

//此致

2 个答案:

答案 0 :(得分:3)

似乎不太可能,但有一个极端边缘情况只会在高度线程化的代码中发生,甚至很少 - 但是技术上可行在您的实现中获得一个线程竞争。最好有:

var handler = Pickedimage
if(handler != null) handler(this, e);

然而!我认为由于订阅者中的错误,订阅事件更有可能引发此错误。查看堆栈跟踪以找出答案。如果你想过分保护事件(所以它不会失败,即使订阅者不好),那么就像:

var handler = Pickedimage;
if(handler != null) {
    foreach (EventHandler<GameEventArgs> subscriber in
        handler.GetInvocationList())
    {
        try {
            subscriber(this, e);
        } catch (Exception ex) {
            Trace(ex);
        }
    }
}

作为脚注,个人我会推迟创建GameEventArgs,直到您知道有人关心,例如:

protected virtual void OnPickedimage(int id, int value)
{
    var handler = Pickedimage;
    if(handler != null) {
        var e = new GameEventArgs(id, value);
        //... and invoke it 
    }
}

答案 1 :(得分:1)

Marc Gravell 指出了正确的方法和解决方案,以防你在大量多线程场景中使用你的控件。有了这些干净的知识,我很想知道当你第一次注意到这个空引用时,你是否有任何订阅者。这是为了简单和基本的事实,如果没有订阅者附加到该事件,您将获得空引用。

public event EventHandler<GameEventArgs> Pickedimage= delegate { };