Câu hỏi Làm thế nào để kích hoạt sự kiện khi giá trị của biến được thay đổi?


Tôi hiện đang tạo một ứng dụng trong C # bằng cách sử dụng Visual Studio. Tôi muốn tạo một số mã để khi một biến có giá trị là 1 thì một đoạn mã nhất định được thực hiện. Tôi biết rằng tôi có thể sử dụng một tuyên bố if nhưng vấn đề là giá trị sẽ được thay đổi trong một quá trình không đồng bộ vì vậy kỹ thuật tuyên bố nếu có thể được bỏ qua trước khi giá trị đã thay đổi.

Có thể tạo trình xử lý sự kiện để khi giá trị biến thay đổi một sự kiện được kích hoạt không? Nếu vậy, làm thế nào tôi có thể làm điều này?

Hoàn toàn có thể là tôi có thể hiểu lầm một câu lệnh if hoạt động như thế nào! Bất kì sự trợ giúp nào đều được đánh giá cao.


76
2018-04-30 14:21


gốc


Chỉ cần được rõ ràng, quan sát thay đổi của biến chỉ có thể cho một biến bạn sở hữu (hoặc đã được IObservable / INotifyPropertyChanged / sự kiện liên quan). Bạn không thể quan sát sự thay đổi của biến hệ thống nếu nó không được thiết kế để quan sát. - Cœur


Các câu trả lời:


Dường như với tôi như bạn muốn tạo ra một tài sản.

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

private int _myProperty;

Điều này cho phép bạn chạy một số mã bất kỳ lúc nào giá trị thuộc tính thay đổi. Bạn có thể nâng cao một sự kiện ở đây, nếu bạn muốn.


95
2018-04-30 14:25





Bạn có thể sử dụng một setter thuộc tính để nâng cao một sự kiện bất cứ khi nào giá trị của một trường sẽ thay đổi.

Bạn có thể có đại diện EventHandler của riêng mình hoặc bạn có thể sử dụng đại biểu System.EventHandler nổi tiếng.

Thông thường có một mô hình cho việc này:

  1. Xác định một sự kiện công khai với một đại biểu xử lý sự kiện (có một đối số kiểu EventArgs).
  2. Xác định phương thức ảo được bảo vệ có tên OnXXXXX (Ví dụ: OnMyPropertyValueChanged). Trong phương thức này, bạn nên kiểm tra xem trình xử lý sự kiện có là null hay không, nếu không bạn có thể gọi nó (nó có nghĩa là có một hoặc nhiều phương thức được gắn với sự kiện ủy nhiệm).
  3. Gọi phương thức được bảo vệ này bất cứ khi nào bạn muốn thông báo cho người đăng ký rằng có điều gì đó đã thay đổi.

Đây là một ví dụ

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

Ưu điểm của phương pháp này là bạn cho phép bất kỳ lớp nào khác muốn kế thừa từ lớp của bạn để thay đổi hành vi nếu cần.

Nếu bạn muốn bắt một sự kiện trong một chủ đề khác mà nó đang được nâng lên, bạn phải cẩn thận không thay đổi trạng thái của các đối tượng được định nghĩa trong một luồng khác mà sẽ gây ra một ngoại lệ cho thread chéo được ném ra. Để tránh điều này, bạn có thể sử dụng một phương thức Invoke trên đối tượng mà bạn muốn thay đổi trạng thái của nó để đảm bảo rằng sự thay đổi đang xảy ra trong cùng một luồng mà sự kiện đã được nâng lên hoặc trong trường hợp bạn đang làm việc với Windows Form có thể sử dụng BackgourndWorker để thực hiện những việc trong một chuỗi song song dễ dàng và dễ dàng.


47
2018-04-30 15:00



Một trong những giải thích tốt nhất trên toàn bộ Web. Tôi nghĩ cuối cùng tôi cũng hiểu được Xử lý sự kiện tùy chỉnh. Cảm ơn bài đăng này. - Ricardo Garcia


.NET framework thực sự cung cấp một giao diện mà bạn có thể sử dụng để thông báo cho các thuê bao khi một thuộc tính đã thay đổi: System.ComponentModel.INotifyPropertyChanged. Giao diện này có một sự kiện PropertyChanged. Nó thường được sử dụng trong WPF cho ràng buộc nhưng tôi đã tìm thấy nó hữu ích trong các lớp kinh doanh như là một cách để chuẩn hóa thông báo thay đổi tài sản.

Về an toàn thread tôi sẽ đặt một khóa dưới trong setter để bạn không chạy vào bất kỳ điều kiện chủng tộc.

Dưới đây là những suy nghĩ của tôi trong mã :):

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

Hy vọng điều này là hữu ích :)


35
2018-04-30 21:13



1 cho việc bao gồm các khóa mà các câu trả lời khác bỏ qua. - ctacke
Việc sử dụng đối tượng _lock là gì? - Lode Vlaeminck
@LodeVlaeminck nó ngăn cản việc thay đổi giá trị của thuộc tính trong khi sự kiện đang được xử lý. - David Suarez


chỉ cần sử dụng một tài sản

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

8
2018-04-30 14:28