Lezen in het Engels

Delen via


Het bijgewerkte .NET Core-gebeurtenispatroon

Vorige

In het vorige artikel zijn de meest voorkomende gebeurtenispatronen besproken. .NET Core heeft een meer ontspannen patroon. In deze versie heeft de EventHandler<TEventArgs> definitie niet langer de beperking die TEventArgs een klasse moet zijn die is afgeleid van System.EventArgs.

Dit verhoogt de flexibiliteit voor u en is compatibel met eerdere versies. Laten we beginnen met de flexibiliteit. De klasse System.EventArgs introduceert één methode: MemberwiseClone(), waarmee een ondiepe kopie van het object wordt gemaakt. Deze methode moet reflectie gebruiken om de functionaliteit ervan te implementeren voor elke klasse die is afgeleid van EventArgs. Deze functionaliteit is eenvoudiger te maken in een specifieke afgeleide klasse. Dat betekent effectief dat het afleiden van System.EventArgs een beperking is die uw ontwerpen beperkt, maar geen extra voordeel biedt. In feite kunt u de definities FileFoundArgs van en SearchDirectoryArgs zodat ze niet worden afgeleid van EventArgs. Het programma werkt precies hetzelfde.

U kunt ook de SearchDirectoryArgs struct wijzigen als u nog een wijziging aanbrengt:

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

De extra wijziging is het aanroepen van de parameterloze constructor voordat u de constructor invoert waarmee alle velden worden geïnitialiseerd. Zonder die toevoeging melden de regels van C# dat de eigenschappen worden geopend voordat ze zijn toegewezen.

U moet de FileFoundArgs waarde van een klasse (verwijzingstype) niet wijzigen in een struct (waardetype). Dat komt doordat het protocol voor het afhandelen van annuleren vereist dat de gebeurtenisargumenten worden doorgegeven via verwijzing. Als u dezelfde wijziging hebt aangebracht, kon de bestandszoekklasse nooit wijzigingen observeren die zijn aangebracht door een van de gebeurtenisabonnees. Er wordt een nieuwe kopie van de structuur gebruikt voor elke abonnee en die kopie zou een andere kopie zijn dan de kopie die wordt gezien door het object voor het zoeken van bestanden.

Laten we nu eens kijken hoe deze wijziging compatibel kan zijn met eerdere versies. Het verwijderen van de beperking heeft geen invloed op bestaande code. Eventuele bestaande gebeurtenisargumenttypen zijn nog steeds afgeleid van System.EventArgs. Compatibiliteit met eerdere versies is een belangrijke reden waarom ze blijven afleiden van System.EventArgs. Alle bestaande gebeurtenisabonnees zijn abonnees van een gebeurtenis die het klassieke patroon heeft gevolgd.

Volgens vergelijkbare logica heeft elk gebeurtenisargumenttype dat nu is gemaakt, geen abonnees in bestaande codebases. Nieuwe gebeurtenistypen die niet worden afgeleid van System.EventArgs , breken deze codebases niet.

Gebeurtenissen met Async-abonnees

U hebt één definitief patroon om te leren: hoe u gebeurtenisabonnees die asynchrone code aanroepen, correct schrijft. De uitdaging wordt beschreven in het artikel over asynchroon en wachtend. Asynchrone methoden kunnen een ongeldig retourtype hebben, maar dat wordt sterk afgeraden. Wanneer uw gebeurtenisabonneecode een asynchrone methode aanroept, hebt u geen andere keuze dan een methode te maken async void . Voor de handtekening van de gebeurtenis-handler is deze vereist.

U moet deze tegengestelde richtlijnen afstemmen. Op een of andere manier moet u een veilige async void methode maken. Hieronder vindt u de basisbeginselen van het patroon dat u moet implementeren:

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

U ziet eerst dat de handler is gemarkeerd als een asynchrone handler. Omdat het wordt toegewezen aan een gemachtigde gebeurtenishandler, heeft het een ongeldig retourtype. Dit betekent dat u het patroon moet volgen dat in de handler wordt weergegeven en dat er geen uitzonderingen mogen worden gegenereerd uit de context van de asynchrone handler. Omdat er geen taak wordt geretourneerd, is er geen taak die de fout kan rapporteren door de foutstatus in te voeren. Omdat de methode asynchroon is, kan de methode de uitzondering niet zomaar genereren. (De aanroepmethode heeft de uitvoering voortgezet omdat deze . async) Het werkelijke runtimegedrag wordt anders gedefinieerd voor verschillende omgevingen. Het kan de thread of het proces dat eigenaar is van de thread beëindigen of het proces in een onbepaalde staat laten staan. Al deze mogelijke resultaten zijn zeer ongewenst.

Daarom moet u de await-instructie verpakken voor de asynchrone taak in uw eigen pogingsblok. Als dit een mislukte taak veroorzaakt, kunt u de fout registreren. Als het een fout is waaruit uw toepassing niet kan herstellen, kunt u het programma snel en probleemloos afsluiten

Dit zijn de belangrijkste updates voor het .NET-gebeurtenispatroon. U ziet veel voorbeelden van de eerdere versies in de bibliotheken waarmee u werkt. U moet echter ook begrijpen wat de nieuwste patronen zijn.

In het volgende artikel in deze reeks kunt u onderscheid maken tussen het gebruik delegates en events in uw ontwerpen. Het zijn vergelijkbare concepten en dat artikel helpt u bij het nemen van de beste beslissing voor uw programma's.

Volgende