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

本文关键字:事件 于空 引用 | 更新日期: 2023-09-27 18:12:51

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

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

代码如下:

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);
        }
    }
}

//问候

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

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

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 
    }
}

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

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