Aracılığıyla paylaş


IncrementingPollingCounter ilk geri çağırma zaman uyumsuz

IncrementingPollingCounter bir ölçümün geçerli değerlerini almak için bir geri çağırma kullanır ve bunu olaylar aracılığıyla EventSource raporlar. Geçmişte, geri çağırmanın ilk çağrısı hangi iş parçacığının etkinleştirildiği EventSourceüzerinde zaman uyumlu olarak gerçekleşebilirdi; gelecekteki çağrılar ayrılmış bir zamanlayıcı iş parçacığında gerçekleşti. .NET 9'dan başlayarak, ilk geri çağırma her zaman zamanlayıcı iş parçacığında zaman uyumsuz olarak gerçekleşir. Bu, sayaç etkinleştirildikten hemen sonra ilk geri çağırma daha sonra gerçekleştiğinden gözlemlenmeyen sayaç değişikliklerine neden olabilir.

Bu değişiklik büyük olasılıkla bir EventListenerdoğrulamak için kullanan IncrementingPollingCounter testleri etkiler. Testler sayacı etkinleştirir ve ardından sayaç tarafından yoklanan durumu hemen değiştirirse, bu değişiklik artık geri çağırma ilk çağrılmadan önce gerçekleşebilir (ve gözden kaçabilir).

Önceki davranış

Daha önce, bir IncrementingPollingCounter etkinleştirildiğinde, geri çağırmanın ilk çağrısı etkinleştirme işlemini gerçekleştiren iş parçacığında zaman uyumlu olarak gerçekleşebilirdi.

Bu örnek uygulama, çağrısı içindeki iş parçacığındaki () => SomeInterestingValue temsilciyi MainEnableEvents()çağırır. Bu geri çağırma 0'ı gözlemler log.SomeInterestingValue . Ayrılmış zamanlayıcı iş parçacığından sonraki bir çağrıda 1 olarak değiştirildiği gözlemlenir log.SomeInterestingValue ve ile Increment value = 1bir olay gönderilir.

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"]}");
        }
    }
}

Yeni davranış

Önceki davranış bölümüyle aynı kod parçacığını kullanarak, geri çağırmanın ilk çağrısı zamanlayıcı iş parçacığında zaman uyumsuz olarak gerçekleşir. İşletim sisteminin birden çok iş parçacığını Main nasıl zamanlamasına bağlı olarak iş parçacığı çalışmadan log.SomeInterestingValue++ önce gerçekleşebilir veya olmayabilir.

Bu zamanlamaya bağlı olarak, uygulama "Increment=0" veya "Increment=1" çıkışını alır.

Sürüm kullanıma sunulmuştur

.NET 9 RC 1

Hataya neden olan değişikliğin türü

Bu değişiklik davranışsal bir değişikliktir.

Değişiklik nedeni

Değişiklik, kilit tutulurken geri çağırma işlevleri çalıştırılırken oluşabilecek olası bir kilitlenmeyi EventListener çözmek için yapılmıştır.

Dış izleme araçlarında ölçümleri görselleştirmek için kullanılan IncrementingPollingCounters senaryolar için eylem gerekmez. Bu senaryolar normal şekilde çalışmaya devam etmelidir.

aracılığıyla EventListenerişlem içi test veya başka sayaç verileri tüketimi yapan senaryolar için kodunuzun adlı EnableEvents()aynı iş parçacığında yapılan sayaç değerinde belirli bir değişikliği gözlemlemeyi bekleip beklemediğini denetleyin. Varsa, değerinden EventListeneren az bir sayaç olayı gözlemlemeyi beklemenizi ve ardından sayaç değerini değiştirmenizi öneririz. Örneğin, örnek kod parçacığının "Increment=1" yazdırdığından emin olmak için öğesine bir ManualResetEventEventListener ekleyebilir, ilk sayaç olayı alındığında sinyal verebilir ve çağrısından log.SomeInterestingValue++önce bekleyebilirsiniz.

Etkilenen API’ler