Dela via


Metodtips för observatörsdesignmönster

I .NET implementeras mönstret för observatörsdesign som en uppsättning gränssnitt. Gränssnittet System.IObservable<T> representerar dataleverantören, som också ansvarar för att tillhandahålla en IDisposable implementering som gör att observatörer kan avbryta prenumerationen på meddelanden. Gränssnittet System.IObserver<T> representerar övervakaren. Det här avsnittet beskriver de metodtips som utvecklare bör följa när de implementerar designmönstret för övervakare med hjälp av dessa gränssnitt.

Threading

Vanligtvis implementerar IObservable<T>.Subscribe en provider metoden genom att lägga till en viss observatör i en prenumerantlista som representeras av ett samlingsobjekt och implementerar IDisposable.Dispose metoden genom att ta bort en viss observatör från prenumerantlistan. En övervakare kan anropa dessa metoder när som helst. Eftersom provider-/observatörskontraktet inte anger vem som ansvarar för att avbryta prenumerationen IObserver<T>.OnCompleted efter återanropsmetoden kan både providern och övervakaren försöka ta bort samma medlem från listan. På grund av den här möjligheten bör både Subscribe metoderna och Dispose vara trådsäkra. Detta innebär vanligtvis att du använder en samtidig samling eller ett lås. Implementeringar som inte är trådsäkra bör uttryckligen dokumentera att de inte är det.

Eventuella ytterligare garantier måste anges i ett lager ovanpå leverantörs-/observatörskontraktet. Implementerare bör tydligt ange när de inför ytterligare krav för att undvika användarförvirring om observatörskontraktet.

Hantera undantag

På grund av den lösa kopplingen mellan en dataprovider och en övervakare är undantag i övervakningsdesignmönstret avsedda att vara informationsmässiga. Detta påverkar hur leverantörer och observatörer hanterar undantag i mönstret för observatörsdesign.

Providern – anropar OnError-metoden

Metoden OnError är avsedd som ett informationsmeddelande till observatörer, ungefär som IObserver<T>.OnNext metoden. Metoden är dock OnNext utformad för att ge en övervakare aktuella eller uppdaterade data, medan OnError metoden är utformad för att indikera att providern inte kan tillhandahålla giltiga data.

Providern bör följa dessa metodtips vid hantering av undantag och anropa OnError metoden:

  • Providern måste hantera sina egna undantag om den har några specifika krav.

  • Leverantören bör inte förvänta sig eller kräva att observatörer hanterar undantag på något visst sätt.

  • Providern bör anropa OnError metoden när den hanterar ett undantag som äventyrar dess möjlighet att tillhandahålla uppdateringar. Information om sådana undantag kan skickas till observatören. I andra fall finns det inget behov av att meddela observatörer om ett undantag.

När leverantören anropar OnError metoden eller IObserver<T>.OnCompleted bör det inte finnas några ytterligare meddelanden och leverantören kan avbryta prenumerationen på sina observatörer. Observatörerna kan dock också avbryta prenumerationen när som helst, inklusive både före och efter att de fått en eller IObserver<T>.OnCompleted flera OnError meddelanden. Mönstret för observatörsdesign avgör inte om leverantören eller observatören ansvarar för att avbryta prenumerationen. Det finns därför en möjlighet att båda kan försöka avbryta prenumerationen. När observatörer avregistrerar sig tas de vanligtvis bort från en prenumerantsamling. I ett entrådat program IDisposable.Dispose bör implementeringen se till att en objektreferens är giltig och att objektet är medlem i prenumerantsamlingen innan du försöker ta bort den. I ett flertrådat program ska ett trådsäkert samlingsobjekt, till exempel ett System.Collections.Concurrent.BlockingCollection<T> objekt, användas.

Observatören – Implementera OnError-metoden

När en observatör får ett felmeddelande från en leverantör bör observatören behandla undantaget som information och bör inte vara skyldig att vidta några särskilda åtgärder.

Övervakaren bör följa dessa metodtips när han eller hon svarar på ett OnError metodanrop från en provider:

  • Övervakaren bör inte utlösa undantag från dess gränssnittsimplementeringar, till exempel OnNext eller OnError. Men om observatören utlöser undantag bör den förvänta sig att dessa undantag inte hanteras.

  • För att bevara anropsstacken bör en övervakare som vill kasta ett Exception objekt som skickades till metoden OnError omsluta undantaget innan det kastas. Ett standardfelobjekt ska användas för detta ändamål.

Ytterligare metodtips

Försök att avregistrera i IObservable<T>.Subscribe metoden kan resultera i en null-referens. Därför rekommenderar vi att du undviker den här metoden.

Även om det är möjligt att koppla en övervakare till flera providrar är det rekommenderade mönstret att endast koppla en IObserver<T> instans till en IObservable<T> instans.

Se även