Share via


Numaralandırmalar (C++/CX)

Windows Çalışma Zamanı türü olayları bildirebilir (yani, yayımlayabilir) ve istemci kodu aynı bileşende veya diğer bileşenlerde olay işleyicileri olarak adlandırılan yöntemleri olayla ilişkilendirerek bu olaylara abone olabilir. Tek bir olayla birden çok olay işleyicisi ilişkilendirilebilir. Yayımlama nesnesi olayı yükselttiğinde, tüm olay işleyicilerinin çağrılmaya neden olur. Bu şekilde, abone olan bir sınıf yayımcı olayı tetiklediğinde uygun olan özel eylemi gerçekleştirebilir. Olay, olaya abone olmak için tüm olay işleyicilerinin sahip olması gereken imzayı belirten bir temsilci türüne sahiptir.

Windows bileşenlerinde olayları kullanma

Windows Çalışma Zamanı içindeki birçok bileşen olayları kullanıma sunar. Örneğin, algılayıcı yeni bir luminescence değeri bildirdiğinde LightSensor nesnesi bir ReadingChanged olayını tetikler. Programınızda bir LightSensor nesnesi kullandığınızda, ReadingChanged olayı tetiklendiğinde çağrılacak bir yöntem tanımlayabilirsiniz. yöntemi istediğiniz her şeyi yapabilir; tek gereksinim, imzasının çağrılan temsilcinin imzası ile eşleşmesi gerektiğidir. Temsilci olay işleyicisi oluşturma ve bir olaya abone olma hakkında daha fazla bilgi için bkz . Temsilciler.

Özel olaylar oluşturma

Bildirim

Bir başvuru sınıfında veya arabirimde bir olay bildirebilir ve genel, iç (genel/özel), genel korumalı, korumalı, özel korumalı veya özel erişilebilirliğe sahip olabilir. Bir olay bildirdiğinizde, derleyici dahili olarak iki erişimci yöntemini kullanıma sunan bir nesne oluşturur: ekleme ve kaldırma. Nesnelere abone olurken olay işleyicileri kaydederken, olay nesnesi bunları bir koleksiyonda depolar. Bir olay tetiklendiğinde, olay nesnesi sırayla listesindeki tüm işleyicileri çağırır. Aşağıdaki örnekteki gibi önemsiz bir olay, örtük bir yedekleme deposunun yanı sıra örtük add ve remove erişimci yöntemlerine sahiptir. Ayrıca, bir özellikte özel get ve set erişimcileri belirtebileceğiniz gibi kendi erişimcilerinizi de belirtebilirsiniz. Uygulayan sınıf, önemsiz bir olaydaki olay abone listesi arasında el ile geçiş yapamaz.

Aşağıdaki örnekte bir olayı bildirme ve tetiklemeyi gösterir. Olayın bir temsilci türü olduğuna ve "^" simgesi kullanılarak bildirildiğini fark edin.

namespace EventTest
{
    ref class Class1;
    public delegate void SomethingHappenedEventHandler(Class1^ sender, Platform::String^ s);

    public ref class Class1 sealed
    {
    public:
        Class1(){}
        event SomethingHappenedEventHandler^ SomethingHappened;
        void DoSomething()
        {
            //Do something....

            // ...then fire the event:
            SomethingHappened(this, L"Something happened.");
        }
    };
}

Kullanım

Aşağıdaki örnek, abone olan bir sınıfın += olaya abone olmak için işlecini nasıl kullandığını ve olay tetiklendiğinde çağrılacak bir olay işleyicisi sağlamayı gösterir. Sağlanan işlevin, ad alanında yayımcı tarafında EventTest tanımlanan temsilcinin imzası ile eşleşir.

namespace EventClient
{
    using namespace EventTest;
    namespace PC = Platform::Collections; //#include <collection.h>

    public ref class Subscriber sealed
    {
    public:
        Subscriber() : eventCount(0) 
        {
            // Instantiate the class that publishes the event.
            publisher= ref new EventTest::Class1();

            // Subscribe to the event and provide a handler function.
            publisher->SomethingHappened += 
                ref new EventTest::SomethingHappenedEventHandler(
                this,
                &Subscriber::MyEventHandler);
            eventLog = ref new PC::Map<int, Platform::String^>();
        }
        void SomeMethod()
        {            
            publisher->DoSomething();
        }

        void MyEventHandler(EventTest::Class1^ mc, Platform::String^ msg)
        {
            // Our custom action: log the event.
            eventLog->Insert(eventCount, msg);
            eventCount++;
        }

    private:
        PC::Map<int, Platform::String^>^ eventLog;
        int eventCount;
        EventTest::Class1^ publisher;
    };
}

Uyarı

Genel olarak, döngüsel başvurulardan kaçınmaya büyük özen göstermediğiniz sürece bir olay işleyicisi için lambda yerine adlandırılmış bir işlev kullanmak daha iyidir. Adlandırılmış bir işlev "bu" işaretçisini zayıf başvuruyla yakalarken, lambda bunu güçlü başvuruyla yakalar ve döngüsel başvuru oluşturur. Daha fazla bilgi için bkz . Zayıf başvurular ve kesme döngüleri (C++/CX).

Özel ekleme ve kaldırma yöntemleri

Dahili olarak, bir olay bir ekleme yöntemine, bir kaldırma yöntemine ve bir raise yöntemine sahiptir. İstemci kodu bir olaya abone olduğunda, ekleme yöntemi çağrılır ve geçirilen temsilci olayın çağırma listesine eklenir. Yayımlama sınıfı olayı çağırır, raise() yönteminin çağrılmaya neden olur ve listedeki her temsilci sırayla çağrılır. Abone, temsilci listesinden kendisini kaldırabilir ve bu da olayın kaldırma yönteminin çağrılabilmesine neden olur. Kodunuzda tanımlamazsanız derleyici bu yöntemlerin varsayılan sürümlerini sağlar; bunlar önemsiz olaylar olarak bilinir. Çoğu durumda tek gereken önemsiz bir olaydır.

Abonelerin eklenmesine veya kaldırılmasına yanıt olarak özel mantık gerçekleştirmeniz gerekiyorsa, bir olay için özel ekleme, kaldırma ve yükseltme yöntemleri belirtebilirsiniz. Örneğin, yalnızca olay raporlaması için gerekli olan pahalı bir nesneniz varsa, bir istemci olaya gerçekten abone olana kadar nesnenin oluşturulmasını büyük ölçüde erteleyebilirsiniz.

Sonraki örnekte, bir olaya özel ekleme, kaldırma ve yükseltme yöntemlerinin nasıl ekleneceği gösterilmektedir:

namespace EventTest2
{
    ref class Class1;
    public delegate void SomethingHappenedEventHandler(Class1^ sender, Platform::String^ msg);

    public ref class Class1 sealed
    {
    public:
        Class1(){}
        event SomethingHappenedEventHandler^ SomethingHappened;
        void DoSomething(){/*...*/}
        void MethodThatFires()
        {
            // Fire before doing something...
            BeforeSomethingHappens(this, "Something's going to happen.");
            
            DoSomething();

            // ...then fire after doing something...
            SomethingHappened(this, L"Something happened.");
        }

        event SomethingHappenedEventHandler^ _InternalHandler;

        event SomethingHappenedEventHandler^ BeforeSomethingHappens
        {
            Windows::Foundation::EventRegistrationToken add(SomethingHappenedEventHandler^ handler)
            {
                // Add custom logic here:
                //....
                return _InternalHandler += handler;
            }

            void remove(Windows::Foundation::EventRegistrationToken token)
            {
                // Add custom logic here:
                //....
                _InternalHandler -= token;
            }

            void raise(Class1^ sender, Platform::String^ str)
            {

                // Add custom logic here:
                //....
                return _InternalHandler(sender, str);
            }
        }
    };
}

Olay işleyicisini abone tarafından kaldırma

Bazı nadir durumlarda, daha önce abone olduğunuz bir olay için olay işleyicisini kaldırmak isteyebilirsiniz. Örneğin, bunu başka bir olay işleyicisiyle değiştirmek veya bu işleyici tarafından tutulan bazı kaynakları silmek isteyebilirsiniz. İşleyiciyi kaldırmak için, işlemden += döndürülen EventRegistrationToken öğesini depolamanız gerekir. Daha sonra bir olay işleyicisini -= kaldırmak için belirteç üzerindeki işlecini kullanabilirsiniz. Ancak, özgün işleyici kaldırıldıktan sonra bile çağrılabilir. Örneğin, olay kaynağı işleyicilerin listesini aldığında ve bunları çağırmaya başladığında bir yarış durumu ortaya çıkabilir. Bu durumda bir olay işleyicisi kaldırılırsa, liste güncel olmaz. Bu nedenle, bir olay işleyicisini kaldırmak istiyorsanız bir üye bayrağı oluşturun. Olay kaldırılırsa ayarlayın ve olay işleyicisinde bayrağı denetleyin ve ayarlandıysa hemen dönün. Sonraki örnekte temel desen gösterilmektedir.

namespace EventClient2
{
    using namespace EventTest2;

    ref class Subscriber2 sealed
    {
    private:
        bool handlerIsActive; 
        Platform::String^ lastMessage;

        void TestMethod()
        {
            Class1^ c1 = ref new Class1();
            handlerIsActive = true;
            Windows::Foundation::EventRegistrationToken cookie =
                c1->SomethingHappened += 
                ref new EventTest2::SomethingHappenedEventHandler(this, &Subscriber2::MyEventHandler);
            c1->DoSomething();

            // Do some other work�..then remove the event handler and set the flag.
            handlerIsActive = false;
            c1->SomethingHappened -= cookie;           
        }

        void MyEventHandler(Class1^ mc, Platform::String^ msg)
        {
            if (!handlerIsActive)
                return;
            lastMessage = msg;
        }
    };
}

Açıklamalar

Aynı olayla birden çok işleyici ilişkilendirilebilir. Olay kaynağı sıralı olarak aynı iş parçacığından tüm olay işleyicilerine çağrır. Olay alıcısı olay işleyicisi yönteminde bloklarsa, olay kaynağının bu olay için diğer olay işleyicilerini çağırmasını engeller.

Olay kaynağının olay alıcılarında olay işleyicilerini çağırma sırası garanti değildir ve çağrıdan çağrıya farklılık gösterebilir.

Ayrıca bkz.

Tür Sistemi
Temsilciler
C++/CX Dil Başvurusu
Ad Alanları Başvurusu