Безопасно ли использовать Activity.Current из нескольких параллельных задач в одном потоке? ⇐ C#
Безопасно ли использовать Activity.Current из нескольких параллельных задач в одном потоке?
При попытке реализовать трассировку W3C, в которой используются переменные, например Activity.Current.SpanId, возник следующий вопрос.
Официальная документация статического свойства Activity.Current гласит:
Получает или задает текущую операцию (Activity) для текущего потока. Это происходит через асинхронные вызовы.
Я не совсем уверен, как интерпретировать потоки между асинхронными вызовами с учетом текущего потока. В современном C# нам больше не нужно заботиться о потоках при использовании задач. Поэтому я ожидаю, что когда я выполняю с помощью workActivity = new Activity($"Work {id}").Start() внутри нескольких рабочих задач, этот экземпляр действия всегда должен возвращаться Activity.Current, даже если несколько задач выполняются в одном потоке (пуле потоков).
Всегда ли это так?
На самом деле все сводится к разнице между контекстом потока и контекстом задачи (если такая вещь вообще существует). Является ли Activity.Current частью контекста потока или частью контекста задачи? Или как Activity.Current всегда отображать правильное значение для каждой параллельной задачи?
Я также провел небольшое исследование, используя этот пример кода:
с использованием System.Diagnostics; пространство имен DummyConsoleApp { Программа внутреннего класса { static void PrintTraceInfo (строка msg, int? workerId = null) { Debug.Assert(Activity.Current != null, "Activity.Current != null"); Console.WriteLine($"Работник {workerId} в потоке {Thread.CurrentThread.ManagedThreadId} с трассировкой {Activity.Current.TraceId} {Activity.Current.ParentSpanId} --> {Activity.Current.SpanId}: {msg}\ н"); } статическая асинхронная работа задачи (int id) { используя var workActivity = new Activity($"Work {id}").Start(); PrintTraceInfo("Работа началась", id); ждать Task.Delay(3000); PrintTraceInfo("Работа завершена", id); } статическая асинхронная задача Main(string[] args) { используя var Activity = new Activity("Main").Start(); PrintTraceInfo("Основное запущено."); вар задачи = новый список(); для (int я = 0; я Work(id)); задачи.Добавить(задача); } ждут Task.WhenAll(задачи).ConfigureAwait(false); PrintTraceInfo("Основное завершено."); } } }с помощью System.Diagnostics; пространство имен DummyConsoleApp { Программа внутреннего класса { static void PrintTraceInfo (строка msg, int? workerId = null) { Debug.Assert(Activity.Current != null, "Activity.Current != null"); Console.WriteLine($"Работник {workerId} в потоке {Thread.CurrentThread.ManagedThreadId} с трассировкой {Activity.Current.TraceId} {Activity.Current.ParentSpanId} --> {Activity.Current.SpanId}: {msg}\ н"); } статическая асинхронная работа задачи (int id) { используя var workActivity = new Activity($"Work {id}").Start(); PrintTraceInfo("Работа началась", id); ждать Task.Delay(3000); PrintTraceInfo("Работа завершена", id); } статическая асинхронная задача Main(string[] args) { используя var Activity = new Activity("Main").Start(); PrintTraceInfo("Основное запущено."); вар задачи = новый список(); для (int я = 0; я Work(id)); задачи.Добавить(задача); } ждут Task.WhenAll(задачи).ConfigureAwait(false); PrintTraceInfo("Основное завершено."); } } } Кажется, все работает как положено, и даже задачи в одном потоке выводят свой индивидуальный идентификатор. Но опять же, это всего лишь небольшое испытание.
Есть ли у кого-нибудь дополнительная информация по этому поводу? Всегда ли можно безопасно получить доступ к Activity.Current из параллельных задач?
При попытке реализовать трассировку W3C, в которой используются переменные, например Activity.Current.SpanId, возник следующий вопрос.
Официальная документация статического свойства Activity.Current гласит:
Получает или задает текущую операцию (Activity) для текущего потока. Это происходит через асинхронные вызовы.
Я не совсем уверен, как интерпретировать потоки между асинхронными вызовами с учетом текущего потока. В современном C# нам больше не нужно заботиться о потоках при использовании задач. Поэтому я ожидаю, что когда я выполняю с помощью workActivity = new Activity($"Work {id}").Start() внутри нескольких рабочих задач, этот экземпляр действия всегда должен возвращаться Activity.Current, даже если несколько задач выполняются в одном потоке (пуле потоков).
Всегда ли это так?
На самом деле все сводится к разнице между контекстом потока и контекстом задачи (если такая вещь вообще существует). Является ли Activity.Current частью контекста потока или частью контекста задачи? Или как Activity.Current всегда отображать правильное значение для каждой параллельной задачи?
Я также провел небольшое исследование, используя этот пример кода:
с использованием System.Diagnostics; пространство имен DummyConsoleApp { Программа внутреннего класса { static void PrintTraceInfo (строка msg, int? workerId = null) { Debug.Assert(Activity.Current != null, "Activity.Current != null"); Console.WriteLine($"Работник {workerId} в потоке {Thread.CurrentThread.ManagedThreadId} с трассировкой {Activity.Current.TraceId} {Activity.Current.ParentSpanId} --> {Activity.Current.SpanId}: {msg}\ н"); } статическая асинхронная работа задачи (int id) { используя var workActivity = new Activity($"Work {id}").Start(); PrintTraceInfo("Работа началась", id); ждать Task.Delay(3000); PrintTraceInfo("Работа завершена", id); } статическая асинхронная задача Main(string[] args) { используя var Activity = new Activity("Main").Start(); PrintTraceInfo("Основное запущено."); вар задачи = новый список(); для (int я = 0; я Work(id)); задачи.Добавить(задача); } ждут Task.WhenAll(задачи).ConfigureAwait(false); PrintTraceInfo("Основное завершено."); } } }с помощью System.Diagnostics; пространство имен DummyConsoleApp { Программа внутреннего класса { static void PrintTraceInfo (строка msg, int? workerId = null) { Debug.Assert(Activity.Current != null, "Activity.Current != null"); Console.WriteLine($"Работник {workerId} в потоке {Thread.CurrentThread.ManagedThreadId} с трассировкой {Activity.Current.TraceId} {Activity.Current.ParentSpanId} --> {Activity.Current.SpanId}: {msg}\ н"); } статическая асинхронная работа задачи (int id) { используя var workActivity = new Activity($"Work {id}").Start(); PrintTraceInfo("Работа началась", id); ждать Task.Delay(3000); PrintTraceInfo("Работа завершена", id); } статическая асинхронная задача Main(string[] args) { используя var Activity = new Activity("Main").Start(); PrintTraceInfo("Основное запущено."); вар задачи = новый список(); для (int я = 0; я Work(id)); задачи.Добавить(задача); } ждут Task.WhenAll(задачи).ConfigureAwait(false); PrintTraceInfo("Основное завершено."); } } } Кажется, все работает как положено, и даже задачи в одном потоке выводят свой индивидуальный идентификатор. Но опять же, это всего лишь небольшое испытание.
Есть ли у кого-нибудь дополнительная информация по этому поводу? Всегда ли можно безопасно получить доступ к Activity.Current из параллельных задач?
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Как создается первый экземпляр Activity из Activity.Current в веб-API asp.net?
Гость » » в форуме C# - 0 Ответы
- 60 Просмотры
-
Последнее сообщение Гость
-
-
-
Как Activity.current.Traceid может быть одинаковой для нескольких запросов?
Anonymous » » в форуме C# - 0 Ответы
- 14 Просмотры
-
Последнее сообщение Anonymous
-