有没有办法让新生成的线程在其父线程上继承ThreadStatic状态(或类似的东西)的值?我想使用这个(或类似的东西)来实现"动态范围"的特殊变量,其中包含用于跟踪/记录等的操作/任务上下文信息.这是一种合理的方法,是否可以使其工作?
我正在阅读帖子中的提示和技巧,我想我会尝试一些我之前从未做过的C#.因此,以下代码没有实际用途,但只是一个'测试函数'来查看发生了什么.
无论如何,我有两个静态私有字段:
private static volatile string staticVolatileTestString = "";
[ThreadStatic]
private static int threadInt = 0;
Run Code Online (Sandbox Code Playgroud)
如您所见,我正在测试ThreadStaticAttribute和volatile关键字.
无论如何,我有一个看起来像这样的测试方法:
private static string TestThreadStatic() {
// Firstly I'm creating 10 threads (DEFAULT_TEST_SIZE is 10) and starting them all with an anonymous method
List<Thread> startedThreads = new List<Thread>();
for (int i = 0; i < DEFAULT_TEST_SIZE; ++i) {
Thread t = new Thread(delegate(object o) {
// The anon method sets a newValue for threadInt and prints the …Run Code Online (Sandbox Code Playgroud) stackoverflow中的这个问题询问[ThreadStatic]是如何实现的: ThreadStatic属性如何工作?
有人建议将它视为Thread对象的扩展.我不确定这是否意味着它基于win32 TLS.
我的问题是,我可以以某种方式从.NET Profiler代码中的当前线程访问[ThreadStatic]的值吗?也就是说,在本机代码中.
例如,如果我能找到使用win32线程id的内存中所有线程静态字段的区域,并找到我需要检索的特定字段.
谢谢
我看过很多关于敏捷 Asp.Net 请求处理的文档?我想知道 WCF 请求处理的情况是否相同。我们可以依靠启动 Wcf 请求处理的 Thread 完成它的事实吗?
我正在维护一个 Wcf 应用程序,其中在很多地方都使用了 ThreadStatic 变量。虽然代码正在运行,但它可靠吗?值得改变它还是应该保持原样?
这不是一个如何自动调用dispose的问题 - 我的问题恰恰相反:我有一个线程池,其中每个线程都有一个ThreadStatic Graphics(由Image创建)来执行文本大小测量.现在我遇到了一个问题,即不时读取TextRenderingHint属性失败(导致ArgumentException),图形似乎被处理掉了.
是否存在一些处理图形的机制,例如,如果线程长时间处于空闲状态?
我有一个我编写的日志框架,它能够跟踪"日志记录上下文".它有一个可插拔的策略框架,但我最常使用的是ThreadStatic变种,它跟踪[ThreadStatic]变量中的上下文.我一直在尝试解决多线程工作流中的日志记录上下文问题.目标是让所有共享公共线程的方法和类的所有调用的所有日志条目记录相同的上下文信息.因为理论上每个线程都应该获得自己的ThreadStatic变量,所以这个想法似乎很容易.
public class ThreadStaticLoggingContextStrategy: ILoggingContextStrategy
{
public ThreadStaticLoggingContextStrategy()
{
Debug.WriteLine("[INITIALIZE] A new instance of 'ThreadStaticLoggingContextStrategy' has been created.");
}
[ThreadStatic] private LoggingContext _context;
public LoggingContext GetLoggingContext()
{
if (_context == null)
_context = new LoggingContext();
return _context;
}
}
Run Code Online (Sandbox Code Playgroud)
实际上,似乎ThreadStatic数据实际上是跨线程共享的.这违背了我对线程的理解.我很难搞清楚问题是什么,直到我投入额外的日志条目,跟踪每个线程清除线程上下文时(所有线程在主循环上运行...在开始时,如果必要的消息是收到,上下文被初始化,并且在finally子句的最后,它被重置.)以下日志记录是CONSISTENT:
[2011-12-15 16:27:21,233] [DEBUG] [TPI.LTI.Eventing.GroupCreatedNotificationHandler:TPI.LTI.Provisioning.Handlers.GroupCreatedNotificationHandler.WORKDEVELOPMENT.1_Thread:324] :( ContextId = 184e82dd-152b-4bb5- a2c6-3e05b2365c04; TransactionId = 1a11130e-e8dd-4fa1-9107-3b46dcb4ffd6; HandlerName = GroupCreatedNotificationHandler; HandlerId = WORKDEVELOPMENT.1)将工具'0967e031-398f-437d-8949-2a17fe844df0'的事件推送到 http://tpidev.pearsoncmg. com/tpi/lti/service/event ...
[2011-12-15 16:27:21,259] [DEBUG] [TPI.LTI.Facades.LTIFacade:TPI.LTI.Provisioning.Handlers.GroupCreatedNotificationHandler.WORKDEVELOPMENT.1_Thread:299] :( ContextId = 184e82dd-152b-4bb5- a2c6-3e05b2365c04; TransactionId = 1a11130e-e8dd-4fa1-9107-3b46dcb4ffd6; HandlerName = GroupCreatedNotificationHandler; HandlerId …
请考虑这些sceanrios:
我试图找出一种方法来设置"逻辑"特定数据,这些数据可以在"逻辑"http请求期间一致地访问,即,如果数据是在"BeginExecute"部分中的线程中设置的,那么该异步处理程序您会考虑,即使ASP.NET在不同的OS/.Net线程上执行"EndExecute"部分,该数据也可以在该asnc处理程序的"EndExecute"部分中使用.
此外,我希望在第二个请求被分配给先前分配给第一个http请求的线程的时候,在随后的http请求中,在"BeginExecute"部分中设置的任何OS/.Net线程中的数据都不可用.它位于"BeginExecute"部分,但是当第一个http请求进入异步操作时,该线程被释放(并且它可能仍在完成其异步操作).
我相信.Net中的"逻辑线程"或"逻辑线程上下文"这个词实际上意味着我提到的相同的"逻辑"操作流程(而不是继续重新分配的底层OS/.Net线程).如果从工作流角度来看,每个http请求都是一个新的"逻辑"操作(即使多个用户按顺序或并行调用相同的Web服务,每个请求都是一个新的和部分逻辑操作),并且在此意思是,"逻辑"操作是一次性的,不能重复.但是,相同的底层OS/.Net线程可以根据其可用性到达时映射到"逻辑"操作.
另外,我想将此数据公开为HttpContext.Current类的静态属性.对于某些人来说,这可能会让人感到意外,但如果您使用的是异步.asmx Web服务方法,则HttpContext.Current无法正常工作.我确信我已经阅读了网上的内容,其中说HttpContext.Current应该总是返回正确的HttpContext,但我在.asmx web-methods的EndExecuteMethod中看到它为null.如果有人可以确认我是否正确地做出我的最后陈述,那将是很好的,但这个陈述不是我试图在这里提出的整体问题.
在阅读了大量文献后(例如log4net.ThreadContext和log4net.LogicalThreadContext之间有什么区别?,http://msmvps.com/blogs/jon_skeet/archive/2010/11/08/the-importance-of-context -and-a-question-of-explicitness.aspx,http://blog.stephencleary.com/2013/04/implicit-async-context-asynclocal.html以及更多包括MSDN文档),以下是我的推论:
现在来问题:
一个很长的问题,有很多参考文献,但希望我做得很好,答案也会让其他人受益.
我想弄清楚单身模式设计.我想从我的单例类为每个线程创建单独的实例.所以我在下面提供了两个设计.
这是工作
class Program
{
static void Main(string[] args)
{
Task.Factory.StartNew(() => Console.WriteLine(SingletonClass.Instance.GetHashCode()));
Task.Factory.StartNew(() => Console.WriteLine(SingletonClass.Instance.GetHashCode()));
Console.ReadLine();
}
}
public sealed class SingletonClass
{
[ThreadStatic]
private static SingletonClass _instance;
public static SingletonClass Instance
{
get
{
if (_instance == null)
{
_instance = new SingletonClass();
}
return _instance;
}
}
private SingletonClass()
{
}
}
Run Code Online (Sandbox Code Playgroud)
它不起作用(抛出NullReferenceException并且没有创建实例.)
class Program
{
static void Main(string[] args)
{
Task.Factory.StartNew(() => Console.WriteLine(SingletonClass.Instance.GetHashCode()));
Task.Factory.StartNew(() => Console.WriteLine(SingletonClass.Instance.GetHashCode()));
Console.ReadLine();
}
}
public sealed class SingletonClass
{
[ThreadStatic]
private …Run Code Online (Sandbox Code Playgroud) 是否有可能在单个请求中使用线程静态变量?当前代码使用线程静态变量进行日志记录,现在我们希望使用异步控制器方法(使用async和await模式),这会导致问题,因为在打开新线程时该变量为null.
asp.net threadstatic async-await asp.net-web-api requestscope
每次等待完成"选项"时,是否正在使用ThreadStatic并设置上下文?还有另外一种方法吗?
public async void Test()
{
// This is in Thread 1
Foo foo = new Foo();
Context.context = "context1"; // This is ThreadStatic
string result = await foo.CallAsynx();
// This is most likely Thread 2
Context.context = "context1"; // This might be a different thread and so resetting context
}
Run Code Online (Sandbox Code Playgroud)
如果我不想使用ThreadStatic,现在有另一种方法吗?
我们有一个相当大的现有代码库,用于构建在ASP.NET之上的各种web服务,并且该代码大量使用访问HttpContext.Current.User(包装为Client.User),我相当确定内部使用它[ThreadStatic]来为您提供环境范围.
我目前正在研究是否有可能我们开始以形式使用更多的异步代码,async/await但我很难找到如何使用[ThreadStatic]它.[ThreadStatic]由于其大量使用,实际上不可能消除对依赖的依赖.
我的理解是,当await命中时,代码的执行在那里停止,调用立即返回,并且设置延续以在异步代码返回时继续执行.同时,原始线程可以自由地用于其他事情,例如处理另一个请求.到目前为止我对它的理解.
我无法真正找到一个确定的答案HttpContext.Current.User是,在之前和之后是否保证是相同的await.
所以基本上:
HttpContext.Current.User = new MyPrincipal();
var user = HttpContext.Current.User;
await Task.Delay(30000);
// Meanwhile, while we wait for that lots of other requests are being handled,
// possibly by this thread.
Debug.Assert(object.ReferenceEquals(HttpContext.Current.User, user));
Run Code Online (Sandbox Code Playgroud)
这有Debug.Assert保证会成功吗?
如果另一个请求由与Task.Delay挂起的相同的线程处理,那么该请求将设置一个不同的HttpContext.Current.User,那么在调用continuation时以某种方式存储和恢复的先前状态是什么?
我可以想象的是,在幕后,[ThreadStatic]状态被保存为线程本身的某种字典,并且当一个线程返回到线程池后返回await该字典时,该字典在某处保持安全并且在设置回线程时它执行延续(或者在一个线程上,我不确定它是否一定是处理延续的同一个线程),可能是对屁股的鼓励和"去得到他们的男孩!",但最后部分可能只是我的想象力.
这有点准确吗?
更新:我试图将一个小试验放在一起尝试这个.到目前为止它似乎工作,并且断言没有因为数百个请求中的任何一个而失败.谁能验证测试是否有意义?
threadstatic ×11
c# ×9
asp.net ×3
async-await ×3
.net ×2
asynchronous ×2
c#-4.0 ×1
graphics ×1
idisposable ×1
logging ×1
profile ×1
requestscope ×1
scope ×1
singleton ×1
volatile ×1
wcf ×1