2011-04-30 36 views
72

Actualmente estoy creando una aplicación en C# usando Visual Studio. Quiero crear un código para que cuando una variable tenga un valor de 1, se lleve a cabo un determinado código. Sé que puedo usar una instrucción if, pero el problema es que el valor se cambiará en un proceso asíncrono, por lo que técnicamente la instrucción if podría ignorarse antes de que el valor haya cambiado.Cómo desencadenar un evento cuando se cambia el valor de una variable?

¿Es posible crear un controlador de eventos para que cuando el valor de la variable cambie se active un evento? Si es así, ¿cómo puedo hacer esto?

¡Es completamente posible que no haya entendido cómo funciona una instrucción if! Cualquier ayuda sería muy apreciada.

+1

Para que quede claro, observando el cambio de una variable sólo es posible para una variable es el propietario (o lo que es ya IObservable/INotifyPropertyChanged/Event-related). No puede observar un cambio en la variable del sistema si no fue diseñado para ser observado. –

Respuesta

90

Me parece que desea crear una propiedad.

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

Esto le permite ejecutar algunos códigos cada vez que cambia el valor de la propiedad. Podrías plantear un evento aquí, si quisieras.

8

sólo tiene que utilizar una propiedad

int _theVariable; 
public int TheVariable{ 
    get{return _theVariable;} 
    set{ 
    _theVariable = value; 
    if (_theVariable == 1){ 
     //Do stuff here. 
    } 
    } 
} 
45

Se puede utilizar un regulador de propiedad para provocar un evento cada vez que el valor de un campo va a cambiar.

Puede tener su propio delegado de EventHandler o puede usar el famoso delegado System.EventHandler.

Por lo general, hay un patrón para esto:

  1. definir un evento público con un delegado controlador de eventos (que tiene un argumento de tipo EventArgs).
  2. Defina un método virtual protegido llamado OnXXXXX (OnMyPropertyValueChanged por ejemplo). En este método, debe verificar si el delegado del controlador de eventos es nulo y si no puede llamarlo (significa que hay uno o más métodos asociados a la delegación del evento).
  3. Llame este método protegido siempre que desee notificar a los suscriptores que algo ha cambiado.

He aquí un ejemplo

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

La ventaja de este enfoque es que deja que ninguna otra clase que quieren heredar de su clase con el fin de cambiar el comportamiento en caso de necesidad.

Si desea capturar un evento en un subproceso diferente que se está iniciando, debe tener cuidado de no cambiar el estado de los objetos definidos en otro subproceso lo que provocará que se genere una excepción de cadena cruzada. Para evitar esto, puede usar un método de Invoke en el objeto que desea cambiar su estado para asegurarse de que el cambio está sucediendo en el mismo hilo que el evento se ha planteado o en caso de que se trate de un formulario de Windows que puede usar un BackgourndWorker para hacer las cosas en un hilo paralelo agradable y fácil.

32

El .NET framework realmente proporciona una interfaz que puede usar para notificar a los suscriptores cuando una propiedad ha cambiado: System.ComponentModel.INotifyPropertyChanged. Esta interfaz tiene un evento PropertyChanged. Su uso habitual en WPF es vinculante, pero lo he encontrado útil en capas comerciales como una manera de estandarizar la notificación de cambio de propiedad.

En términos de seguridad de la rosca, pondría un candado en el setter para que no se encuentre en ninguna condición de carrera.

Éstos son mis pensamientos en el código :):

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

la esperanza que esto es útil :)

+5

+1 para la inclusión del bloqueo que las otras respuestas omiten. – ctacke

+1

¿Cuál es el uso del objeto _lock? –

+1

@LodeVlaeminck impide cambiar el valor de la propiedad mientras se procesa el evento. –

Cuestiones relacionadas