2011-04-30 45 views
72

我目前使用Visual Studio在C#中创建应用程序。我想创建一些代码,以便当变量的值为1时执行某段代码。 我知道我可以使用if语句,但问题是值会在异步过程中更改,因此技术上if语句可能在值更改之前被忽略。如何在变量值更改时触发事件?

是否有可能创建一个事件处理程序,以便在变量值更改时触发一个事件?如果是这样,我该怎么做?

我完全可能误解了if语句的工作原理!任何帮助将非常感激。

+1

只是要清楚,观察变量的变化才有可能为您自己的变量(或者是已经IObservable/INotifyPropertyChanged /事件相关)。如果系统变量没有被设计为可观察的,你就无法观察系统变量的变化。 – 2014-07-11 09:39:47

回答

90

对我来说就像你想创建一个属性。

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

这使您可以随时在属性值更改时运行一些代码。如果你愿意,你可以在这里举办一个活动。

8

只需使用一个属性

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

可以使用属性setter提高每当一个字段的值是不会改变的事件。

您可以拥有自己的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在并行线程中做一些很好很容易的事情。

32

.NET框架实际上提供了一个接口,您可以使用该接口在属性发生更改时通知订户:System.ComponentModel.INotifyPropertyChanged。这个接口有一个事件PropertyChanged。它通常用于WPF绑定,但我发现它在业务层中用作标准化属性更改通知的一种方法。

就线程安全性而言,我会在setter中放置一个锁,以便您不会遇到任何竞争条件。

这里是我的代码的想法:):

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

希望这是有益:)

+5

+1为包含其他答案省略的锁。 – ctacke 2011-04-30 23:35:18

+1

对象_lock有什么用处? – 2015-01-27 10:05:55

+1

@LodeVlaeminck它可以防止在处理事件时更改属性的值。 – 2016-04-15 07:30:16

相关问题