A IncrementingPollingCounter kezdeti visszahívása aszinkron

IncrementingPollingCounter visszahívással lekéri egy metrika aktuális értékeit, és eseményeken keresztül EventSource jelenti. Korábban előfordulhatott, hogy a visszahívás első meghívása szinkron módon történt azon a szálon, amely lehetővé tette az EventSource; a jövőbeli hívásokat egy dedikált időzítőszálon. A .NET 9-től kezdve az első visszahívás mindig aszinkron módon történik az időzítőszálon. Ez azt eredményezheti, hogy a számláló engedélyezése után történt számlálómódosítások nem lesznek fenntartva, mert az első visszahívás később történik.

Ez a változás nagy valószínűséggel hatással lesz az ellenőrzésre EventListenerhasznált IncrementingPollingCounter tesztekre. Ha a tesztek engedélyezik a számlálót, majd azonnal módosítják a számláló által lekérdezett állapotot, ez a módosítás a visszahívás első meghívásakor (és észrevétlenül) fordulhat elő.

Előző viselkedés

Korábban, amikor egy IncrementingPollingCounter engedélyezve lett, előfordulhat, hogy a visszahívás első hívása szinkron módon történt az engedélyezési műveletet végrehajtó szálon.

Ez a mintaalkalmazás meghívja a hívás szálán lévő meghatalmazottat () => SomeInterestingValueMain.EnableEvents() Ez a visszahívás a 0-t fogja megfigyelni log.SomeInterestingValue . Egy dedikált időzítőszál log.SomeInterestingValue későbbi hívása 1-re változik, és a rendszer egy eseményt küld a következővel Increment value = 1: .

using System.Diagnostics.Tracing;

var log = MyEventSource.Log;
using var listener = new Listener();

log.SomeInterestingValue++;

Console.ReadKey();

class MyEventSource : EventSource
{
    public static MyEventSource Log { get; } = new();
    private IncrementingPollingCounter? _counter;
    public int SomeInterestingValue;

    private MyEventSource() : base(nameof(MyEventSource))
    {
        _counter = new IncrementingPollingCounter("counter", this, () => SomeInterestingValue);
    }
}

class Listener : EventListener
{
    protected override void OnEventSourceCreated(EventSource eventSource)
    {
        if (eventSource.Name == nameof(MyEventSource))
        {
            EnableEvents(eventSource, EventLevel.Informational, EventKeywords.None,
                new Dictionary<string, string?> { { "EventCounterIntervalSec", "1.0" } });
        }
    }

    protected override void OnEventWritten(EventWrittenEventArgs eventData)
    {
        if (eventData.EventSource.Name == "EventCounters")
        {
            var counters = (IDictionary<string, object>)eventData.Payload![0]!;
            Console.WriteLine($"Increment: {counters["Increment"]}");
        }
    }
}

Új viselkedés

Az Előző viselkedés szakasz kódrészletét használva a visszahívás első meghívása aszinkron módon történik az időzítőszálon. Előfordulhat, hogy a Main szál futtatása log.SomeInterestingValue++ előtt nem fordul elő, attól függően, hogy az operációs rendszer hogyan ütemez több szálat.

Az időzítéstől függően az alkalmazás a "Increment=0" vagy a "Increment=1" kimenetet adja ki.

Bevezetett verzió

.NET 9 RC 1

A kompatibilitástörő változás típusa

Ez a változás viselkedésbeli változás.

A változás oka

A módosítás egy potenciális holtpont feloldására történt, amely visszahívási függvények futtatásakor fordulhat elő a EventListener zárolás megtartása közben.

A külső monitorozási eszközök metrikáinak vizualizációjára szolgáló IncrementingPollingCounters forgatókönyvek esetében nincs szükség műveletre. Ezeknek a forgatókönyveknek továbbra is normálisan kell működniük.

A folyamaton belüli tesztelést vagy a számlálóadatok EventListenermás módon történő felhasználását végző forgatókönyvek esetében ellenőrizze, hogy a kód arra számít-e, hogy a számláló értékének egy konkrét módosítását fogja-e megfigyelni a hívott EnableEvents()szálon. Ha igen, javasoljuk, hogy várja meg, hogy megfigyeljen legalább egy számlálóeseményt a EventListenerszámlálóból, majd módosítsa a számláló értékét. Ha például azt szeretné, hogy a példakódrészlet "Increment=1" nyomatot nyomjon, hozzáadhat egy ManualResetEvent értéket a EventListenerszámlálóhoz, jelezheti azt az első számlálóesemény fogadásakor, és várjon rá a hívás log.SomeInterestingValue++előtt.

Érintett API-k