在.NET中使用线程本地存储的最佳实践是什么?

时间:2008-10-06 16:47:54

标签: .net multithreading thread-local

我的应用程序中有一个要求我认为可以通过使用线程本地存储来满足,但我想知道它是否是最好避免的事情之一。

我已经阅读了一些关于这个主题的文章:

http://www.dotnetcoders.com/web/Articles/ShowArticle.aspx?article=58

http://msdn.microsoft.com/en-us/library/system.threadstaticattribute(vs.80).aspx

我知道 如何使用它,我只是想知道我是否应使用它。

有任何建议,需要注意哪些?

[编辑]

以下是用例:

我通过一些对每个查询进行大量日志记录的方法来汇集所有数据访问权限。我记录的一件事是命令文本的完整转储,其中填写了命令,这样我就可以直接从跟踪日志中复制粘贴到Sql Management Studio中。

在我的网络应用程序中使用global.asax向我发送电子邮件给管理员尽可能多的信息,当我得到未处理的异常时。当我收到SqlException时,我想将sql命令转储文本放入此电子邮件中,这样可以节省因查询而导致页面爆炸时挖掘跟踪日志的时间。

我不想改变我的数据访问类的方法签名,所以我可以在堆栈中一直传递一些引用,只是为了在我得到异常时将其删除。我在想TLS可能是一个放置“lastsqlcommand”之类的好地方,但这看起来不是一个可行的解决方案。

3 个答案:

答案 0 :(得分:7)

asp.net应用程序的问题:处理单个请求可能会切换线程,即如果同一会话中存在并行请求。因此,在HttpApplication.PostRequireRequestState事件之前放入TLS的任何内容可能以后都不存在,因为您位于不同的线程上。

[由提问者编辑]

对于我的特定用例,我最终在SqlException.Data字典中添加了一个键值对,然后在记录异常详细信息时检索该字典。这给了我希望使用线程本地存储的功能。

答案 1 :(得分:6)

线程本地存储是修复在线程之前设计并使用大量全局变量和静态的库的快速方法。这是C标准库在不改变其接口的情况下实现线程安全的方式(在内部,许多函数使用静态缓冲区)。

一般来说,这对于这个目的有好处。如果必须在多线程环境中拥有全局数据,那么线程本地存储是一种很好的方法。一个常见的原因是,您正在调用第三方函数,该函数在同一个堆栈框架中调用您,但是没有为您提供传递额外信息的钩子 - 当您尝试将旧C库包装起来时,这种情况会发生很多.NET。

答案 2 :(得分:0)

查看新的.net 4 ThreadLocal<T>课程,其中包含一个示例,更多信息here