যখন কোনও ভেরিয়েবলের মান পরিবর্তন হয় তখন কীভাবে ইভেন্টটি ট্রিগার করা যায়?


97

আমি বর্তমানে ভিজুয়াল স্টুডিও ব্যবহার করে সি # তে একটি অ্যাপ্লিকেশন তৈরি করছি। আমি কিছু কোড তৈরি করতে চাই যাতে ভেরিয়েবলের যখন 1 এর মান হয় তবে একটি নির্দিষ্ট কোডের কাজ করা হয়। আমি জানি যে আমি একটি স্টেট স্টেটমেন্ট ব্যবহার করতে পারি তবে সমস্যাটি হ'ল অ্যাসিঙ্ক্রোনাস প্রক্রিয়াতে মানটি পরিবর্তিত হবে তাই প্রযুক্তিগতভাবে যদি মানটি পরিবর্তনের আগে বিবৃতিটিকে উপেক্ষা করা যায়।

কোনও ইভেন্ট হ্যান্ডলার তৈরি করা কি সম্ভব যাতে ভেরিয়েবলের মান পরিবর্তন হলে কোনও ইভেন্ট ট্রিগার হয়? যদি তা হয় তবে আমি কীভাবে এটি করতে পারি?

এটা সম্পূর্ণ সম্ভব যে আমি যদি ভুলভাবে বুঝতে পারি যে যদি বিবৃতিটি কীভাবে কাজ করে! কোন সাহায্যের অনেক প্রশংসা হবে।


4
কেবল পরিষ্কারভাবেই বলা যায় যে কোনও ভেরিয়েবলের পরিবর্তন পর্যবেক্ষণ করা কেবলমাত্র আপনার নিজের (বা যা ইতিমধ্যে IObservable / INotifyPropertyChanged / ইভেন্ট সম্পর্কিত) ভেরিয়েবলের পক্ষে সম্ভব। আপনি যদি সিস্টেমের পরিবর্তনশীল পরিবর্তনটি পর্যবেক্ষণের জন্য ডিজাইন না করে থাকেন তবে তা পর্যবেক্ষণ করতে পারবেন না।
সিউর

উত্তর:


125

আমার কাছে মনে হয় আপনি কোনও সম্পত্তি তৈরি করতে চান।

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

private int _myProperty;

এটি আপনাকে যে কোনও সময় সম্পত্তি মান পরিবর্তনের সাথে সাথে কিছু কোড চালানোর অনুমতি দেয়। আপনি চাইলে এখানে একটি ইভেন্ট তুলতে পারেন।


67

যখনই কোনও ক্ষেত্রের মান পরিবর্তন হতে চলেছে আপনি কোনও ইভেন্ট সেটার জন্য কোনও সম্পত্তি সেটার ব্যবহার করতে পারেন।

আপনার নিজের ইভেন্ট হ্যান্ডলার প্রতিনিধি থাকতে পারে বা আপনি বিখ্যাত সিস্টেম.এভেন্টহ্যান্ডলার প্রতিনিধি ব্যবহার করতে পারেন।

সাধারণত এটির জন্য একটি নিদর্শন রয়েছে:

  1. ইভেন্ট হ্যান্ডলার প্রতিনিধি সহ একটি সর্বজনীন ইভেন্টের সংজ্ঞা দিন (এতে ইভেন্টআর্গস টাইপের যুক্তি রয়েছে)।
  2. অনএক্সএক্সএক্সএক্সএক্সএক্স নামে একটি সুরক্ষিত ভার্চুয়াল পদ্ধতি সংজ্ঞায়িত করুন (উদাহরণস্বরূপ 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();
    }
 }

এই পদ্ধতির সুবিধাটি হ'ল আপনি যদি প্রয়োজন হয় তবে আপনার ক্লাস থেকে উত্তরাধিকারী হতে চাইলে যে কোনও ক্লাসকে অনুমতি দিন।

যদি আপনি কোনও ইভেন্টটিকে উত্থিত করা হয় এমন কোনও ভিন্ন থ্রেডে ধরতে চান তবে আপনাকে অবশ্যই সতর্ক থাকতে হবে যে অন্য থ্রেডে সংজ্ঞায়িত বস্তুর অবস্থা পরিবর্তন না করা উচিত যা ক্রস থ্রেড ব্যতিক্রম ছুঁড়ে দেওয়ার কারণ হতে পারে। এটি এড়ানোর জন্য আপনি যে কোনও ইভেন্টটি উত্থাপিত হয়েছে একই থ্রেডে ঘটছে বা আপনি যদি উইন্ডোজ ফর্মের সাথে লেনদেন করছেন সে ক্ষেত্রে পরিবর্তনটি ঘটছে কিনা তা নিশ্চিত করার জন্য আপনি যে পদটিতে তার অবস্থার পরিবর্তন করতে চান তার উপর একটি ইনভোক পদ্ধতি ব্যবহার করতে পারেন you সমান্তরাল থ্রেডে সুন্দর এবং সহজে কাজগুলিতে ব্যাকগ্র্যান্ড ওয়ার্কার ব্যবহার করতে পারেন।


4
পুরো ওয়েবের সেরা ব্যাখ্যাগুলির মধ্যে একটি। আমি মনে করি আমি শেষ পর্যন্ত কাস্টম ইভেন্ট হ্যান্ডলিংটি বুঝতে পারি। এই পোস্টের জন্য ধন্যবাদ।

44

.NET ফ্রেমওয়ার্কটি এমন একটি ইন্টারফেস সরবরাহ করে যা আপনি যখন কোনও সম্পত্তি পরিবর্তিত হয় তখন গ্রাহকগণকে অবহিত করার জন্য ব্যবহার করতে পারেন: সিস্টেম.কম্পোনমোডেল.আইনোটাইফ্রোপার্টিচেন্জড। এই ইন্টারফেসটির একটি ইভেন্ট সম্পত্তি পরিবর্তন হয়েছে। এটি সাধারণত বাঁধাইয়ের জন্য ডাব্লুপিএফ-এ ব্যবহৃত হয় তবে সম্পত্তি পরিবর্তনের বিজ্ঞপ্তিটি মানক করার উপায় হিসাবে আমি ব্যবসায়িক স্তরগুলিতে এটি দরকারী বলে মনে করেছি।

থ্রেড সুরক্ষার ক্ষেত্রে আমি সেটারের নীচে একটি লক রাখব যাতে আপনি কোনও রেসের শর্তে না চলে।

কোডে আমার ধারণা এখানে রয়েছে:

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

আশা করি এটি সহায়ক হবে :)


6
অন্যান্য উত্তরগুলি বাদ দেয় এমন লকটি অন্তর্ভুক্ত করার জন্য +1।
সিটিএক

4
লক অবজেক্টের ব্যবহার কী?
লোড ভ্লাইমিন্ক

4
@ লোডভ্লেইমিন্ক ইভেন্টটি প্রক্রিয়া চলাকালীন এটি সম্পত্তিটির মান পরিবর্তন করা রোধ করে।
ডেভিড সুয়ারেজ

আইএমএইচও, এটি একটি লকের জন্য একটি বিজোড় জায়গা। [যদি না অন্য তালাটি অন্য কোথাও ব্যবহার না করা হয় যা ভিন্ন পরিস্থিতি]] যদি দুটি পৃথক থ্রেড ভাগ করে নেওয়া সম্পত্তি নির্ধারণের জন্য রেস অবস্থায় থাকে, তবে সম্পত্তির "চূড়ান্ত" অবস্থা নির্দোষ নয়। পরিবর্তে এমন কিছু প্যাটার্ন ব্যবহার করুন যেখানে একটি থ্রেড সম্পত্তির "মালিকানাধীন" থাকে এবং কেবল তারা সেট করে। যা প্যাটার্ন পরিস্থিতি উপর নির্ভর করে। (যদি সত্যিই থ্রেডগুলির মধ্যে মালিকানা পরিবর্তন করতে হয় তবে একটি লাঠি / টোকেন পাস করুন)) যদি আমি এখানে কোনও তালাবন্ধের প্রয়োজনের মুখোমুখি হই তবে আমি সামগ্রিক নকশাটি যত্ন সহকারে পরীক্ষা করব। OTOH, এখানে একটি লক নিরীহ is
টুলমেকারস্টেভ


1

একটি সহজ পদ্ধতিতে ভেরিয়েবলের উপর গেট এবং সেট ফাংশন ব্যবহার করে


    using System;
    public string Name{
    get{
     return name;
    }
    
    set{
     name= value;
     OnVarChange?.Invoke();
    }
    }
    private string name;
    
    public event System.Action OnVarChange;


0

আপনি জেনেরিক ক্লাস ব্যবহার করতে পারেন:

class Wrapped<T>  {
    private T _value;

    public Action ValueChanged;

    public T Value
    {
        get => _value;

        set
        {
            OnValueChanged();
            _value = value;
        }
    }

    protected virtual void OnValueChanged() => ValueChanged?.Invoke() ;
}

এবং নিম্নলিখিতগুলি করতে সক্ষম হবেন:

var i = new Wrapped<int>();

i.ValueChanged += () => { Console.WriteLine("changed!"); };

i.Value = 10;
i.Value = 10;
i.Value = 10;
i.Value = 10;

Console.ReadKey();

ফলাফল:

changed!
changed!
changed!
changed!
changed!
changed!
changed!
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.