简体   繁体   English

在C#中使用事件处理程序

[英]Using an Event Handler in C#

I am trying to watch a value in c#, and trigger a function when it changes. 我正在尝试观察c#中的值,并在其更改时触发一个函数。 Based on reading examples, I have: 根据阅读示例,我有:

//event watcher //事件观察者

private int _currentFrame =1;
public event System.EventHandler FrameChanged;

protected virtual void OnFrameChanged()
{
    if (FrameChanged != null) FrameChanged(this, EventArgs.Empty);
}

public int Age
{
    get
    {
        return _currentFrame;
    }

    set
    {
        //#3
        _currentFrame = value;
        OnFrameChanged();
    }
}

and in my main function: 在我的主要职能中:

_currentFrame += _currentFrame;

As I understand it, this should trigger the event watcher, but it does not. 据我了解,这应该触发事件观察器,但事实并非如此。 What have i missed? 我错过了什么?

Thanks. 谢谢。

您尚未为FrameChanged分配任何事件。

yourInstance.FrameChanged+= () => DoSomething();

There are two things you need to do in order to get an event handler to be called. 要调用事件处理程序,您需要做两件事。

  1. You need to hook the event handler to the event 您需要将事件处理程序挂接到事件上
  2. You need to fire the event 您需要触发事件

You have neglected to show the first item in your code. 您已忽略了在代码中显示第一项。 If you haven't hooked up an event handler to your event you need to do that. 如果您尚未将事件处理程序连接到事件,则需要这样做。 You could do it like this: 您可以这样做:

someObject.FrameChanged += SomeObjectFrameChanged;

...

private void SomeObjectFrameChanged(object sender, EventArgs e)
{
    ... code here
}

The second looks OK on the surface, the property calls OnFrameChanged. 第二个在表面上看起来不错,该属性调用OnFrameChanged。

By the way, your OnFrameChanged is not the recommended way to implement event handler fire methods, you should use this template: 顺便说一句,不建议您使用OnFrameChanged实现事件处理程序触发方法,您应该使用以下模板:

protected virtual void OnFrameChanged()
{
    var evt = FrameChanged;
    if (evt != null) evt(this, EventArgs.Empty);
}

The reason for this change, lifting the event value into a local variable is that if you're in a multithreaded environment, after you've checked that the event has at least one event handler ( != null ), another thread could unsubscribe the last event handler. 进行此更改的原因是,将事件值提升为局部变量是因为,如果您处于多线程环境中,则在检查事件至少具有一个事件处理程序( != null )之后,另一个线程可以取消订阅该事件处理程序!= null最后一个事件处理程序。 Nitpicking but you should still change it. 细细挑选,但您仍然应该更改它。

In C# 6 you can change the above method to this: 在C#6中,您可以将上述方法更改为:

protected virtual void OnFrameChanged()
{
    FrameChanged?.Invoke(this, EventArgs.Empty);
}

As this will do all the same things. 因为这将做所有相同的事情。


But here we come to the real bug in your code and expectations: 但是在这里,我们来看看您的代码和期望中的真正错误:

_currentFrame += _currentFrame;

You expect this to fire your event, but this is incorrect. 您希望这会触发您的事件,但这是不正确的。

You're accessing the backing field directly, which bypasses all the code in the property, thus there is no code here that calls OnFrameChanged and thus the event will not be fired. 您正在直接访问后备字段,该字段将绕过属性中的所有代码,因此此处没有调用OnFrameChanged代码,因此不会触发该事件。

Instead you should access the property : 相反,您应该访问该属性

Age += Age;

Minor nitpicking #2 is that you should ensure that PropertyChanged is only fired if the property actually changed: 次要挑剔#2是您应确保仅在属性实际更改时才触发PropertyChanged

Age = 1;
Age = 1; // did not change, do not fire PropertyChanged

And thus you should implement your property setter like this: 因此,您应该像这样实现属性设置器:

set
{
    if (_currentFrame == value) return;

    //#3
    _currentFrame = value;
    OnFrameChanged();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM