C# 使用线程本地存储的内存泄漏?
几天后,我们的网站显然出现了大于2Gb/池的内存泄漏。因此,我在windbg上运行了一些命令,最后发现了一些东西:有许多System.LocalDataStoreElement。在下面的源代码中快速搜索后,我发现了一个真正的stange类:C# 使用线程本地存储的内存泄漏?,c#,asp.net-mvc,memory-leaks,windbg,thread-local-storage,C#,Asp.net Mvc,Memory Leaks,Windbg,Thread Local Storage,几天后,我们的网站显然出现了大于2Gb/池的内存泄漏。因此,我在windbg上运行了一些命令,最后发现了一些东西:有许多System.LocalDataStoreElement。在下面的源代码中快速搜索后,我发现了一个真正的stange类: public class HomeController { public HomeController() { CultureInfoManager.SetCulture(MyCompany.Internal.Enumerat
public class HomeController
{
public HomeController()
{
CultureInfoManager.SetCulture(MyCompany.Internal.Enumerations.Site.GbEn);
}
}
public class CultureInfoManager
{
[ThreadStaticAttribute]
private static Language _language;
public static void SetCulture(Site site)
{
if (site == Site.Undefined) return;
//strange ???
var localSlot = Thread.AllocateDataSlot();
Thread.SetData(localSlot, site.Code());
_language = site.GetLanguage();
var cultureInfo = CreateCultureInfo(site);
Thread.CurrentThread.CurrentCulture = cultureInfo;
Thread.CurrentThread.CurrentUICulture = cultureInfo;
}
private static CultureInfo CreateCultureInfo(Site site)
{
if (site == Site.Undefined) site = Site.GbEn;
var languageCode = site.GetLanguage().Code();
switch (languageCode)
{
case "f2":
return new CultureInfo("fr-FR");
case "br":
return new CultureInfo("pt-BR");
case "s1":
return new CultureInfo("es-AR");
case "s2":
return new CultureInfo("es-CL");
case "e1":
return new CultureInfo("en-CA");
default:
return new CultureInfo(languageCode);
}
}
public static Language GetCurrentLanguage()
{
return _language;
}
}
所以,我的问题是:
在这里使用Thread.AllocateDataSlot显然是无用的,但它能解释内存泄漏吗?因为在完成了超过40万个请求的负载测试之后,我无法重现泄漏。
对web应用程序使用TLS/ThreaStatic是否相关?因为在asp.net中,我们不控制线程的生命周期和一个线程,因为工作线程将执行许多请求。
我还在KB女士身上发现了一个问题
总之,所有内容似乎都在这段代码上,但我无法重现这个问题。我重申,绝对不要在ASP.NET应用程序中使用ThreadStatic。我看到你在做一些本地化工作。我将为此使用一个route参数。这是更好的搜索引擎优化方面。然后,您可以拥有一个全局操作属性,该属性将读取此路由参数并设置当前线程区域性,以便它可用于整个请求。谢谢,感谢Never,Never,Never,但请解释一下为什么?那么Thread.AllocateDataSlot呢?因为没有任何东西可以保证每个请求都由不同的线程提供服务。正如您所知,ASP.NET使用线程池为请求提供服务。通过使用ThreadStatic属性,您基本上将对象的生存期绑定到线程,而不是请求。更糟糕的是,您可能有两个完全不同的请求,由来自ASP.NET的完全相同的线程提供服务,这意味着您将在用户之间得到非常糟糕的数据混合。事情就更复杂了。例如,如果您使用异步控制器,您可以。。。持续相同的请求可以由两个不同的线程提供服务。您可以在一个线程上启动请求,在另一个线程上完成它。通过将变量绑定到线程,您完全混合了对象的生命周期。