我在我的应用程序中有一个要求,我认为可以通过使用线程本地存储来满足,但我想知道它是否是最好避免的事情之一.
我已经阅读了一些关于这个主题的文章:
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"之类的好地方,但这看起来不是一个可行的解决方案.
asp.net应用程序的问题:处理单个请求可能会切换线程,即如果同一会话中存在并行请求.因此,在HttpApplication.PostRequireRequestState事件之前放入TLS的任何内容可能在以后都不存在,因为您在不同的线程上.
[由提问者编辑]
对于我的特定用例,我最终将一个键值对添加到SqlException.Data字典中,然后在记录异常详细信息时检索该字典.这给了我希望使用线程本地存储的功能.
线程本地存储是修复在线程之前设计并使用大量全局变量和静态的库的快速方法.这是C标准库在不更改其接口的情况下实现线程安全的方式(在内部,许多函数使用静态缓冲区).
一般来说,它有利于此目的.如果必须在多线程环境中拥有全局数据,那么线程本地存储是一种很好的方法.一个常见的原因是你正在调用第三方函数,它在同一个堆栈框架中调用你,但是没有为你提供传递额外信息的钩子 - 当你尝试将旧的C库包装起来时,这种情况会发生很多.净.