C# 如何存储一个值并使其在整个";“请求”;有或没有HttpContext?

C# 如何存储一个值并使其在整个";“请求”;有或没有HttpContext?,c#,.net-core,C#,.net Core,在我的应用程序可能同时服务于HTTP请求并在后台工作(无HTTP上下文)的场景中,当我不一定能够在处理程序之间传递值时,如何使值在整个请求中全局可用 示例1:(http,已解决) 请求作为HTTP请求进入,因此存在HTTP上下文。这个请求有一些头,我不仅需要这些头来处理请求,还需要将这些头中的任何跟踪ID转发到任何下游服务请求。这不是问题,因为我可以从流中的任何位置访问HttpContext。我的记录器可以将其添加到日志中,但我的命名HTTP客户端也可以使用自定义处理程序进行设置,以便始终从原始

在我的应用程序可能同时服务于HTTP请求并在后台工作(无HTTP上下文)的场景中,当我不一定能够在处理程序之间传递值时,如何使值在整个请求中全局可用

示例1:(http,已解决) 请求作为HTTP请求进入,因此存在HTTP上下文。这个请求有一些头,我不仅需要这些头来处理请求,还需要将这些头中的任何跟踪ID转发到任何下游服务请求。这不是问题,因为我可以从流中的任何位置访问HttpContext。我的记录器可以将其添加到日志中,但我的命名HTTP客户端也可以使用自定义处理程序进行设置,以便始终从原始请求中访问这些头,以便更新它们并保持跟踪

示例2:(非http) 同一个应用程序也可能有一个消息总线使用者在运行,因此当它拾取要处理的消息时,没有HTTP上下文。相反,它会查看消息负载或消息头来查找这些跟踪ID。由于由于此消息而发生的任何传出请求的自定义消息处理程序取决于它们是否是原始http上下文,它将从中获取这些跟踪ID,因此它不再工作,因为它将始终为null

我需要某种方法来存储作用域为“请求”的值,无论其是否为http,并且它们需要全局可访问,因为在某些情况下我无法传递值(例如,启动期间设置的项目,如日志记录)

我的第一个想法是使用在DI中注册的作用域服务。我会称它为
FooContext
,也许它有一些方法可以让我更新它的内部值。然后,我可以请求
FooContext
的应用程序中的任何其他地方都应该收到一个作用域副本以及该请求的当前状态。我在这方面的结果好坏参半:

为了测试,我旋转了两个线程,每个线程都有自己的服务范围。假设我为
FooContext
注册了一个作用域服务,每次请求时都返回一个新实例。用法如下:

var thread1=新线程开始(()=>{
var serviceScope=\u serviceProvider.CreateScope().serviceProvider;
var context=serviceScope.GetService();
增加价值(“某些”、“事物”);
});
var thread2=新的ThreadStart(()=>{
var serviceScope=\u serviceProvider.CreateScope().serviceProvider;
var context=serviceScope.GetService();
增加价值(“某些”、“其他价值”);
});
在前几次运行中,看起来每个线程都有自己的
FooContext
实例,但最终,我开始看到一些交叉。现在我意识到线程不一定等于“请求”,但这是我唯一能想到的分离服务范围的方法。我对其他测试方法持开放态度


有更好的方法吗?对其他想法也持开放态度。TIA

一个选项可能是注册一个类为
InstancePerLifetimeScope
(用Autofac的说法)。如果您在处理消息总线方面正确设置了生存期作用域(例如,您可能需要在消息处理之前创建一个新的生存期作用域),那么它将在web和消息处理上下文中工作。您的根本问题是支持跟踪ID
AsyncLocal
可能值得研究。@mjwills-是的,这就是MSDI术语中的“作用域”。我的结果好坏参半,但我想我可能刚刚发现了原因——实施不同的方案存在问题。事实上,这可能仍然是正确的答案。至于
AsyncLocal
我正在调查。。。我仍在试图了解它与
ThreadLocal
的区别,以及在这种情况下我将如何使用它。一个选项可能是注册一个名为
InstancePerLifetimeScope
(用Autofac的说法)的类。如果您在处理消息总线方面正确设置了生存期作用域(例如,您可能需要在消息处理之前创建一个新的生存期作用域),那么它将在web和消息处理上下文中工作。您的根本问题是支持跟踪ID
AsyncLocal
可能值得研究。@mjwills-是的,这就是MSDI术语中的“作用域”。我的结果好坏参半,但我想我可能刚刚发现了原因——实施不同的方案存在问题。事实上,这可能仍然是正确的答案。至于
AsyncLocal
我正在调查。。。我仍在试图理解它与ThreadLocal的区别,以及在这种情况下我将如何使用它。