Jegyzet
Az oldalhoz való hozzáférés engedélyezést igényel. Próbálhatod be jelentkezni vagy könyvtárat váltani.
Az oldalhoz való hozzáférés engedélyezést igényel. Megpróbálhatod a könyvtár váltását.
A Windows futtatókörnyezet típusa deklarálhatja (vagyis közzéteheti) az eseményeket, és az ugyanabban az összetevőben vagy más összetevőkben lévő ügyfélkód feliratkozhat ezekre az eseményekre az eseménykezelőknek nevezett metódusok társításával. Egyetlen eseményhez több eseménykezelő is társítható. Amikor a közzétételi objektum elindítja az eseményt, az az összes eseménykezelő meghívását eredményezi. Ily módon a feliratkozó osztály bármilyen egyéni műveletet végrehajthat, amikor a közzétevő előhozta az eseményt. Egy esemény delegálttípussal rendelkezik, amely megadja azt az aláírást, amellyel minden eseménykezelőnek rendelkeznie kell ahhoz, hogy előfizethessen az eseményre.
Események felhasználása Windows-összetevőkben
A Windows futtatókörnyezetben számos összetevő tesz közzé eseményeket. Egy LightSensor-objektum például egy ReadingChanged eseményt aktivál, amikor az érzékelő új fényességértéket jelez. Amikor LightSensor-objektumot használ a programban, meghatározhat egy metódust, amelyet a ReadingChanged esemény aktiválásakor hívunk meg. A módszer azt tehet, amit csak szeretne; Az egyetlen követelmény az, hogy az aláírásnak meg kell egyeznie a meghívott meghatalmazott aláírásával. A delegált eseménykezelő létrehozásáról és az eseményre való feliratkozásról további információt a Meghatalmazottak című témakörben talál.
Egyéni események létrehozása
Nyilatkozat
Egy eseményt ref osztályban vagy felületen deklarálhat, és nyilvános, belső (nyilvános/privát), nyilvános, védett, privát védelem alatt álló vagy privát akadálymentességgel rendelkezhet. Esemény deklarálásakor a fordító belsőleg létrehoz egy objektumot, amely két kiegészítő módszert tesz elérhetővé: hozzáadás és eltávolítás. Amikor az objektumok előfizetése regisztrálja az eseménykezelőket, az eseményobjektum egy gyűjteményben tárolja őket. Egy esemény aktiválásakor az eseményobjektum a listában szereplő összes kezelőt meghívja. Egy triviális esemény – mint az alábbi példában látható – implicit háttértárolóval, valamint implicit add és remove kiegészítő metódusokkal rendelkezik. Saját tartozékokat is megadhat, ugyanúgy, ahogyan egyéni get és set tartozékokat is megadhat egy tulajdonságon. A implementálási osztály nem tudja manuálisan végigjárni az esemény-előfizetők listáját egy triviális eseményben.
Az alábbi példa bemutatja, hogyan deklarálhat és aktiválhat egy eseményt. Figyelje meg, hogy az esemény delegált típusú, és a "^" szimbólummal deklarálva van.
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.");
}
};
}
Használat
Az alábbi példa bemutatja, hogy egy előfizetési osztály hogyan használja az operátort az += eseményre való feliratkozásra, és hogyan biztosít egy eseménykezelőt az esemény indításakor. Figyelje meg, hogy a megadott függvény megegyezik a névtér közzétevő oldalán EventTest definiált meghatalmazott aláírásával.
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;
};
}
Figyelmeztetés
Általában érdemesebb egy elnevezett függvényt használni a lambda helyett egy eseménykezelőhöz, kivéve, ha nagy gondot fordít a körkörös hivatkozások elkerülésére. Egy elnevezett függvény gyenge hivatkozással rögzíti az "ez" mutatót, míg a lambda erős hivatkozással rögzíti, és körkörös hivatkozást hoz létre. További információ: Gyenge hivatkozások és törésciklusok (C++/CX).
Egyéni hozzáadási és eltávolítási módszerek
Az események belsőleg hozzáadási, eltávolítási és emelési metódussal is rendelkeznek. Amikor az ügyfélkód előfizet egy eseményre, a rendszer meghívja a hozzáadási metódust, és az átadott meghatalmazott bekerül az esemény meghívási listájába. A közzétételi osztály meghívja az eseményt, meghívja a emelés() metódust, és a listában szereplő összes meghatalmazottat meghívja. Az előfizető eltávolíthatja magát a delegáltak listájából, ami az esemény eltávolítási metódusának meghívását eredményezi. A fordító ezen metódusok alapértelmezett verzióit biztosítja, ha nem definiálja őket a kódban; ezeket triviális eseményeknek nevezzük. Sok esetben csak egy triviális eseményre van szükség.
Egyéni hozzáadási, eltávolítási és emelési módszereket is megadhat egy eseményhez, ha egyéni logikát kell végrehajtania az előfizetők hozzáadására vagy eltávolítására válaszul. Ha például van egy költséges objektuma, amely csak az eseményjelentéshez szükséges, akkor lazán elhalaszthatja az objektum létrehozását, amíg az ügyfél ténylegesen elő nem iratkozhat az eseményre.
A következő példa bemutatja, hogyan adhat hozzá egyéni hozzáadási, eltávolítási és emelési metódusokat egy eseményhez:
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);
}
}
};
}
Eseménykezelő eltávolítása az előfizetői oldalról
Bizonyos ritka esetekben előfordulhat, hogy el szeretné távolítani egy eseménykezelőt egy olyan eseményről, amelyre korábban előfizetett. Előfordulhat például, hogy lecseréli egy másik eseménykezelőre, vagy törölni szeretne néhány, az általa tárolt erőforrást. Kezelő eltávolításához a műveletből += visszaadott EventRegistrationTokent kell tárolnia. Ezután a -= jogkivonaton lévő operátorral eltávolíthat egy eseménykezelőt. Az eredeti kezelő azonban még az eltávolítás után is meghívható. Egy versenyfeltétel például akkor fordulhat elő, ha az esemény forrása lekéri a kezelők listáját, és elkezdi meghívni őket. Ha egy eseménykezelő el lesz távolítva, miközben ez történik, a lista elavulttá válik. Ha tehát el szeretne távolítani egy eseménykezelőt, hozzon létre egy tagjelölőt. Állítsa be, ha az esemény el lett távolítva, majd az eseménykezelőben ellenőrizze a jelölőt, és azonnal térjen vissza, ha be van állítva. A következő példa az alapmintát mutatja be.
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;
}
};
}
Megjegyzések
Több kezelő is társítható ugyanahhoz az eseményhez. Az eseményforrás egymás után meghívja az összes eseménykezelőt ugyanabból a szálból. Ha egy eseménykezelő letiltja az eseménykezelő metódust, az megakadályozza, hogy az eseményforrás más eseménykezelőket invokálásra invokálást invokálásra invokálása az eseményhez.
Az eseményforrás eseménykezelők meghívásának sorrendje nem garantált, és eltérhet a hívástól.
Lásd még
Típus rendszer
meghatalmazottak
C++/CX nyelvi referencia
Névterek – referencia