1

我只需要引发一个自定义事件并且我想实现它。

这是界面:

public delegate void Back();

interface IGoBack
{
    event Back GoBack;
    void ExecuteGoBack();
}

这是一个有效的实现:

public partial class LiveView : UserControl, IGoBack
{
    public LiveView()
    {
        InitializeComponent();
    }

    public event Back GoBack;
    public void ExecuteGoBack()
    {
        GoBack();
    }

    private void btnGoBack_Click(object sender, EventArgs e)
    {
        ExecuteGoBack();
    }
}

这不起作用(事件出现空指针异常):

    public partial class ViolationsControl : UserControl, IGoBack
{
    public ViolationsControl()
    {
        InitializeComponent();
    }

    public event Back GoBack;

    public void ExecuteGoBack()
    {
        if(GoBack!=null)GoBack();
    }

    private void btnGoBack_Click(object sender, EventArgs e)
    {
        ExecuteGoBack();
    }
}

你认为我做错了什么?

4

1 回答 1

2

引发事件通常是这样实现的:

public void RaiseGoBack()
{
    var handler = GoBack;
    if(handler == null)
        return;
    handler();
}

这种实现的原因是线程安全。在您的代码中,有人可能在您实际调用它之后但在您实际调用它之前分离了最后一个if处理程序 。在这种情况下GoBacknull尽管您进行了检查。
上面的实现通过拍摄当前附加的处理程序的“快照”并对这个快照执行检查和调用来解决这个问题。

话虽如此,您需要附加调试器或检查堆栈跟踪以验证NullReferenceException. 我上面概述的问题是所谓的竞争条件。如果您不大量使用多个线程,通常不会发生这种情况。
这意味着您的异常很可能是在其他地方引起的,很可能是在某个事件处理程序中。

于 2013-02-19T07:48:07.433 回答