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

これは機能していません (イベントでの NULL ポインタの例外):

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

この実装の理由はスレッドセーフです。あなたのコードでは、 実際に呼び出す前に、誰かが最後のハンドラーを切り離している可能性があります。この場合、あなたのチェックにもかかわらずです。 上記の実装では、現在アタッチされているハンドラーの「スナップショット」を取得し、このスナップショットでチェックと呼び出しを実行することで、この問題を解決しています。ifGoBacknull

そうは言っても、デバッガーをアタッチするか、スタック トレースをチェックして、NullReferenceException. 上で概説した問題は、いわゆる競合状態です。複数のスレッドを頻繁に使用していない場合、通常は発生しません。
これは、例外が別の場所で発生する可能性が最も高いことを意味します。最も可能性が高いのは、イベント ハンドラーの 1 つです。

于 2013-02-19T07:48:07.433 に答える