Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
IncrementingPollingCounter использует обратный вызов для получения текущих значений метрик и сообщает о нем с помощью EventSource событий. В прошлом первое вызов обратного вызова, возможно, произошло синхронно на любом потоке, включающего EventSource; будущие вызовы произошли в выделенном потоке таймера. Начиная с .NET 9 первый обратный вызов всегда выполняется асинхронно в потоке таймера. Это может привести к изменениям счетчика, произошедшим сразу после включения счетчика, так как первый обратный вызов происходит позже.
Это изменение, скорее всего, влияет на тесты, используемые EventListener для проверки IncrementingPollingCounter. Если тесты позволяют включить счетчик, а затем немедленно изменить состояние, которое опрашивать счетчик, это изменение может произойти до первого вызова обратного вызова (и не замечено).
Прежнее поведение
Ранее при включении первого вызова обратного вызова, возможно, IncrementingPollingCounter произошла синхронная синхронизация в потоке, который выполнял операцию включения.
В этом примере приложения вызывается делегат () => SomeInterestingValue в Main потоке в вызове EnableEvents(). Этот обратный вызов будет наблюдаться log.SomeInterestingValue 0. Последующий вызов из выделенного потока таймера будет наблюдать log.SomeInterestingValue за изменением 1, и событие будет отправлено с 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"]}");
}
}
}
Новое поведение
Используя тот же фрагмент кода, что и в разделе "Предыдущее поведение ", первый вызов обратного вызова выполняется асинхронно в потоке таймера. Это может произойти Main до выполнения log.SomeInterestingValue++ потока в зависимости от того, как ОС планирует несколько потоков.
В зависимости от этого времени приложение выводит "Increment=0" или "Increment=1".
Представленные версии
.NET 9 RC 1
Тип критического изменения
Причина изменения
Это изменение было внесено для устранения потенциальной взаимоблокировки, которая может возникать при выполнении функций обратного вызова во время EventListener блокировки.
Рекомендуемое действие
Никаких действий не требуется для сценариев, которые используются IncrementingPollingCounters для визуализации метрик во внешних средствах мониторинга. Эти сценарии должны продолжать работать нормально.
Для сценариев, выполняющих внутрипроцессное тестирование или другое потребление данных счетчика, EventListenerпроверьте, ожидается ли в коде определенное изменение значения счетчика, сделанного в том же потоке, который называется EnableEvents(). Если это так, рекомендуется ждать, чтобы наблюдать по крайней мере одно событие счетчика из него EventListener, а затем изменить значение счетчика. Например, чтобы убедиться, что пример фрагмента кода печатает "Increment=1", можно добавить в ManualResetEventEventListenerнего сигнал, когда получено первое событие счетчика, и подождите его до вызова log.SomeInterestingValue++.