Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
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 moet zijn afgeleid van System.EventArgs.
Dit verhoogt de flexibiliteit voor u en is compatibel met eerdere versies. Laten we beginnen met de flexibiliteit. De implementatie voor System.EventArgs maakt gebruik van een methode gedefinieerd in System.Object: MemberwiseClone(), waarmee een ondiepe kopie van het object wordt gemaakt. Deze methode moet reflectie gebruiken om de functionaliteit 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 van FileFoundArgs en SearchDirectoryArgs wijzigen, zodat ze niet worden afgeleid van EventArgs. Het programma werkt precies hetzelfde.
U kunt de SearchDirectoryArgs ook wijzigen in een struct 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 rapporteren de regels van C# dat de eigenschappen worden geopend voordat ze worden toegewezen.
U moet de FileFoundArgs niet wijzigen van een klasse (verwijzingstype) in een struct (waardetype). Het protocol voor het afhandelen van annuleren vereist dat u gebeurtenisargumenten doorgeeft per 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. Bestaande gebeurtenisargumenttypen zijn nog steeds afgeleid van System.EventArgs. Compatibiliteit met eerdere versies is een belangrijke reden waarom ze blijven afleiden van System.EventArgs. Bestaande gebeurtenisabonnees zijn abonnees van een gebeurtenis die het klassieke patroon heeft gevolgd.
Volgens vergelijkbare logica zou elk gebeurtenisargumenttype dat nu is gemaakt, geen abonnees in bestaande codebases hebben. Nieuwe gebeurtenistypen die niet zijn afgeleid van System.EventArgs breken deze codebases niet.
Gebeurtenissen met Async-abonnees
Je hebt nog één laatste patroon om te leren: hoe je gebeurtenisabonnees die asynchrone code aanroepen correct schrijft. De uitdaging wordt beschreven in het artikel over async en await. Asynchrone methoden kunnen een ongeldig retourtype hebben, maar dat wordt afgeraden. Wanneer uw gebeurtenisabonneecode een asynchrone methode aanroept, heeft u geen andere keuze dan een async void-methode te maken. Voor de handtekening van de gebeurtenis-handler is dit vereist.
U moet deze tegengestelde richtlijnen afstemmen. Op een of andere manier moet u een veilige async void methode maken. De basisbeginselen van het patroon dat u moet implementeren, worden weergegeven in de volgende code:
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 gedelegeerde gebeurtenishandler, heeft het een void retourtype. Dit betekent dat u het patroon moet volgen zoals aangegeven in de handler en dat er geen uitzonderingen mogen optreden buiten 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 genereren. (De aanroepende methode blijft doorgaan omdat deze is async.) Het werkelijke gedrag tijdens runtime wordt verschillend gedefinieerd voor diverse 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.
U moet de await-expressie 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
In dit artikel worden de belangrijkste updates van het .NET-gebeurtenispatroon uitgelegd. Mogelijk ziet u veel voorbeelden van de eerdere versies in de bibliotheken waarmee u werkt. U moet echter ook begrijpen wat de nieuwste patronen zijn. U ziet de voltooide code voor het voorbeeld op Program.cs.
In het volgende artikel in deze reeks kunt u onderscheid maken tussen het gebruik van 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.