Как вызвать событие при изменении значения переменной? - PullRequest
88 голосов
/ 30 апреля 2011

В настоящее время я создаю приложение на C # с использованием Visual Studio.Я хочу создать некоторый код, чтобы, когда переменная имела значение 1, выполнялся определенный фрагмент кода.Я знаю, что могу использовать оператор if, но проблема в том, что значение будет изменено в асинхронном процессе, поэтому технически оператор if можно было бы игнорировать до изменения значения.

Возможно ли создать событиеобработчик, чтобы при изменении значения переменной происходило событие?Если так, как я могу это сделать?

Вполне возможно, что я мог неправильно понять, как работает оператор if!Любая помощь будет высоко ценится.

Ответы [ 4 ]

110 голосов
/ 30 апреля 2011

Мне кажется, что вы хотите создать свойство.

public int MyProperty
{
    get { return _myProperty; }
    set
    {
        _myProperty = value;
        if (_myProperty == 1)
        {
            // DO SOMETHING HERE
        }
    }
}

private int _myProperty;

Это позволяет запускать некоторый код в любое время, когда изменяется значение свойства. Вы можете поднять событие здесь, если хотите.

58 голосов
/ 30 апреля 2011

Вы можете использовать установщик свойств, чтобы вызывать событие всякий раз, когда значение поля будет меняться.

Вы можете иметь свой собственный делегат EventHandler или использовать известный делегат System.EventHandler.

Обычно для этого есть шаблон:

  1. Определение открытого события с делегатом обработчика событий (с аргументом типа EventArgs).
  2. Определение защищенного виртуального методаназывается OnXXXXX (например, OnMyPropertyValueChanged).В этом методе вы должны проверить, является ли делегат обработчика событий нулевым, и если нет, вы можете вызвать его (это означает, что к делегированию события присоединен один или несколько методов).
  3. Вызывайте этот защищенный метод всякий раз, когда вы хотитечтобы уведомить подписчиков, что что-то изменилось.

Вот пример

private int _age;

//#1
public event System.EventHandler AgeChanged;

//#2
protected virtual void OnAgeChanged()
{ 
     if (AgeChanged != null) AgeChanged(this,EventArgs.Empty); 
}

public int Age
{
    get
    {
         return _age;
    }

    set
    {
         //#3
         _age=value;
         OnAgeChanged();
    }
 }

Преимущество этого подхода состоит в том, что вы позволяете любым другим классам, которые хотят наследовать от вашего класса, изменитьсяповедение при необходимости.

Если вы хотите перехватить событие в другом потоке, который вызывается, вы должны быть осторожны, чтобы не изменить состояние объектов, определенных в другом потоке, что вызовет исключение между потокамибыть брошенным.Чтобы избежать этого, вы можете использовать метод Invoke для объекта, для которого вы хотите изменить его состояние, чтобы убедиться, что изменение происходит в том же потоке, в котором было инициировано событие, или в случае, если вы имеете дело с формой Windows, которую выможно использовать BackgourndWorker, чтобы делать вещи в параллельном потоке красиво и легко.

43 голосов
/ 01 мая 2011

.NET Framework фактически предоставляет интерфейс, который вы можете использовать для уведомления подписчиков при изменении свойства: System.ComponentModel.INotifyPropertyChanged.Этот интерфейс имеет одно событие PropertyChanged.Обычно он используется в WPF для привязки, но я нашел его полезным на бизнес-уровнях для стандартизации уведомлений об изменениях свойств.

С точки зрения безопасности потоков, я бы поставил блокировку в установщике, чтобы вы не 'Я не могу столкнуться с любыми условиями гонки.

Вот мои мысли в коде :):

public class MyClass : INotifyPropertyChanged
{
    private object _lock;

    public int MyProperty
    {
        get
        {
            return _myProperty;
        }
        set
        {
            lock(_lock)
            {
                //The property changed event will get fired whenever
                //the value changes. The subscriber will do work if the value is
                //1. This way you can keep your business logic outside of the setter
                if(value != _myProperty)
                {
                    _myProperty = value;
                    NotifyPropertyChanged("MyProperty");
                }
            }
        }
    }

    private NotifyPropertyChanged(string propertyName)
    {
        //Raise PropertyChanged event
    }
    public event PropertyChangedEventHandler PropertyChanged;
}


public class MySubscriber
{
    private MyClass _myClass;        

    void PropertyChangedInMyClass(object sender, PropertyChangedEventArgs e)
    {
        switch(e.PropertyName)
        {
            case "MyProperty":
                DoWorkOnMyProperty(_myClass.MyProperty);
                break;
        }
    }

    void DoWorkOnMyProperty(int newValue)
    {
        if(newValue == 1)
        {
             //DO WORK HERE
        }
    }
}

Надеюсь, что это полезно :)

9 голосов
/ 30 апреля 2011

просто используйте свойство

int  _theVariable;
public int TheVariable{
  get{return _theVariable;}
  set{
    _theVariable = value; 
    if ( _theVariable == 1){
      //Do stuff here.
    }
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...