Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 名为数据槽的线程上未保留值_C#_.net_Thread Local Storage - Fatal编程技术网

C# 名为数据槽的线程上未保留值

C# 名为数据槽的线程上未保留值,c#,.net,thread-local-storage,C#,.net,Thread Local Storage,这很简单。我们有这样的代码: var slot = Thread.GetNamedDataSlot("myslot"); Thread.SetData(slot, value); 当前代码退出线程。最后,线程被重新分配以进行更多的工作。我们期望(根据doc和SO中的许多断言)该值仍然存在于槽中。然而,至少有时,情况并非如此。结果是空的。ManagedThreadId与我们为其设置的值相同,但该值已变为null 我们确实调用了一些不透明的第三方程序集,但我认为其他代码无法在不知道其名称的情况下清

这很简单。我们有这样的代码:

var slot = Thread.GetNamedDataSlot("myslot");
Thread.SetData(slot, value);
当前代码退出线程。最后,线程被重新分配以进行更多的工作。我们期望(根据doc和SO中的许多断言)该值仍然存在于槽中。然而,至少有时,情况并非如此。结果是空的。ManagedThreadId与我们为其设置的值相同,但该值已变为null

我们确实调用了一些不透明的第三方程序集,但我认为其他代码无法在不知道其名称的情况下清除该插槽


你有没有想过这是怎么发生的?是不是.net破坏了线程,然后又创建了另一个具有相同id的线程?线程是否在应用程序域中持续存在?

答案是线程不是永远存在的。返回到池中的线程可能被重用,也可能被丢弃。在将TLS中的内容留在线程上时要小心,如果不编写析构函数,可能会导致资源泄漏

这里有一篇文章描述了同样的问题:

线程池线程不属于您。您根本不应该依赖它们的上下文,这包括
ThreadStatic
数据和
LocalDataStoreSlot
之类的内容。运行时可以用线程池线程做很多事情来破坏代码,这一点都不好笑。例如,当您开始使用
wait
(同一方法可以轻松地在多个不同的线程上执行,有些来自线程池,有些不…)时,这种情况会变得更加疯狂

作为一个实现细节(您不应该依赖任何东西),.NET运行时将线程池管理为所需的大小。在一个完全异步的应用程序上,这意味着它只有大约1-2倍的CPU核。但是,如果这些线程被占用,它将开始创建新的线程来容纳排队的工作项(当然,除非池线程实际上正在使CPU饱和——在这种情况下,新线程没有帮助)。当峰值负载完成时,它同样会开始释放线程


ManagedThreadId
AppDomain
的整个生命周期内都不是唯一的-它仅在任何给定时刻是唯一的。您不应该依赖它的唯一性,尤其是在处理线程池线程时。但是,在使用线程池线程时,给定线程在其生命周期内的ID将保持不变(即使底层系统线程发生了变化——当然,假设托管线程实际上是在系统线程之上实现的),您没有使用实际的线程-您只是在线程池上发布工作项。

新线程,新插槽。如果线程存在,则本地存储将消失。我想你需要重新考虑你的设计。当然,leppie,新线程,新插槽。但它不是一个新线程,而是同一个线程,从池中重用。还是这样?现在我发现了,同样的问题。我猜池中的线程不会永远存在,线程id可以重用。您试图解决的问题是什么?看起来你在做一些很奇怪的事情。另外,您可能不想使用命名插槽,因为有更好的选项可用。