A frissített .NET Core-eseményminta
Az előző cikk a leggyakoribb eseménymintákat ismertette. A .NET Core lazább mintával rendelkezik. Ebben a verzióban a EventHandler<TEventArgs>
definíció már nem rendelkezik azokkal a korlátozásokkal, amelyekből TEventArgs
System.EventArgs
az osztálynak származnia kell.
Ez növeli a rugalmasságot, és visszamenőlegesen kompatibilis. Kezdjük a rugalmassággal. A System.EventArgs osztály egy metódust vezet be: MemberwiseClone()
ez hozza létre az objektum sekély másolatát.
Ennek a metódusnak tükrözést kell használnia annak érdekében, hogy a funkcióját bármely, a forrásból EventArgs
származtatott osztályhoz megvalósítsa. Ez a funkció egyszerűbben hozható létre egy adott származtatott osztályban. Ez gyakorlatilag azt jelenti, hogy a System.EventArgs-ből való származtatás olyan kényszer, amely korlátozza a terveket, de nem biztosít további előnyöket.
Valójában módosíthatja FileFoundArgs
a definíciókat, és SearchDirectoryArgs
így azok nem származnak.EventArgs
A program pontosan ugyanúgy fog működni.
Ha még egy módosítást szeretne végezni, a szerkezetet is módosíthatja SearchDirectoryArgs
:
internal struct SearchDirectoryArgs
{
internal string CurrentSearchDirectory { get; }
internal int TotalDirs { get; }
internal int CompletedDirs { get; }
internal SearchDirectoryArgs(string dir, int totalDirs, int completedDirs) : this()
{
CurrentSearchDirectory = dir;
TotalDirs = totalDirs;
CompletedDirs = completedDirs;
}
}
A további módosítás az, hogy meghívja a paraméter nélküli konstruktort, mielőtt az összes mezőt inicializáló konstruktort beírja. E kiegészítés nélkül a C# szabályai azt jelentik, hogy a tulajdonságok a hozzárendelésük előtt érhetők el.
Az osztályt (referenciatípust) ne módosítsa FileFoundArgs
szerkezetre (értéktípusra). Ennek az az oka, hogy a megszakítás kezelésére szolgáló protokoll megköveteli az eseményargumentumok hivatkozással történő átadását. Ha ugyanezt a módosítást hajtotta végre, a fájlkeresési osztály soha nem tudta megfigyelni az esemény előfizetői által végrehajtott módosításokat. A struktúra új példánya minden előfizető számára használható, és ez a másolat más másolat lenne, mint a fájlkeresési objektum által látott másolat.
Most tekintsük át, hogyan lehet ez a módosítás visszamenőlegesen kompatibilis.
A kényszer eltávolítása nem érinti a meglévő kódot. A meglévő eseményargumentumtípusok továbbra is a következőből System.EventArgs
származnak: .
A visszamenőleges kompatibilitás az egyik fő oka annak, hogy továbbra is származni fognak a programból System.EventArgs
. A meglévő esemény-előfizetők a klasszikus mintát követő esemény előfizetői lesznek.
Hasonló logikát követve a most létrehozott eseményargumentum-típusok nem rendelkeznének előfizetőkkel egyetlen meglévő kódbázisban sem. Azok az új eseménytípusok, amelyek nem származnak, System.EventArgs
nem szakítják meg ezeket a kódbázisokat.
Események az Async-előfizetőkkel
Egy utolsó mintát kell megtanulnia: Hogyan írhat helyesen az aszinkron kódot hívó esemény-előfizetőket. A kihívást az aszinkronról szóló cikkben ismertetjük, és várjuk. Az aszinkron metódusok érvénytelen visszatérési típussal rendelkezhetnek, de ez erősen elriasztható. Amikor az esemény-előfizetői kód aszinkron metódust hív meg, nincs más választása, mint létrehozni egy metódust async void
. Az eseménykezelő aláírásához szükség van rá.
Ezt az ellentétes útmutatást össze kell hangolnia. Valahogy létre kell hoznia egy biztonságos async void
módszert. A megvalósítandó minta alapjai az alábbiak:
worker.StartWorking += async (sender, eventArgs) =>
{
try
{
await DoWorkAsync();
}
catch (Exception e)
{
//Some form of logging.
Console.WriteLine($"Async task failure: {e.ToString()}");
// Consider gracefully, and quickly exiting.
}
};
Először figyelje meg, hogy a kezelő aszinkron kezelőként van megjelölve. Mivel egy eseménykezelő delegálttípushoz van rendelve, érvénytelen visszatérési típussal fog rendelkezni. Ez azt jelenti, hogy a kezelőben látható mintát kell követnie, és nem szabad kivételeket kivennie az aszinkron kezelő környezetéből. Mivel nem ad vissza tevékenységet, nincs olyan tevékenység, amely a hibás állapot beírásával jelentheti a hibát. Mivel a metódus aszinkron, a metódus nem tudja egyszerűen kivenni a kivételt. (A hívó metódus továbbra is végrehajtás alatt áll, mert az async
.) A futtatókörnyezet tényleges viselkedése eltérően lesz definiálva a különböző környezetekben. Megszakíthatja a szálat vagy azt a folyamatot, amely a szál tulajdonosa, vagy meghatározhatatlan állapotban hagyhatja a folyamatot. Mindezek a lehetséges eredmények rendkívül nemkívánatosak.
Ezért érdemes az aszinkron tevékenység várakozási utasítását a saját próbablokkjában becsomagolni. Ha ez hibát okoz, naplózhatja a hibát. Ha olyan hiba, amelyből az alkalmazás nem tud helyreállni, gyorsan és kecsesen kiléphet a programból
Ezek a .NET-eseményminta fő frissítései. Számos példát láthat a korábbi verziókra a tárakban, amellyel dolgozik. Azonban meg kell értenie, hogy mik a legújabb minták is.
A sorozat következő cikke segít különbséget tenni a használat delegates
és events
a tervezés között. Ezek hasonló fogalmak, és ez a cikk segít a legjobb döntés meghozatalában a programok számára.