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

7
我在我的应用程序中有一个需求,我认为可以通过使用线程本地存储来满足,但我想知道这是否是最好避免的事情之一。
我已经阅读了一些关于这个主题的文章:

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中。
在我的Web应用程序的global.asax中,当我遇到未处理的异常时,我会向管理员发送尽可能多的信息的电子邮件。 当我收到SqlException时,我想将该sql命令转储文本放入此电子邮件中,这样当页面因查询而崩溃时,我就可以节省挖掘跟踪日志的时间。
我不想更改我的数据访问类的方法签名,只是为了在出现异常时传递一些引用,然后再将其取出。 我曾经考虑过TLS可能是放置"lastsqlcommand"之类内容的好地方,但这似乎不是可行的解决方案。

我一直避免使用线程本地存储,并找到了另一种完成相同操作的方法。我的想法一直是线程本地存储可能比直接访问更慢(不确定这是否正确)。我也很想知道其他人的想法。 - dongola7
3个回答

7
一个 ASP.NET 应用程序的坑点:单个请求的处理可能会切换线程,即在同一会话中存在并行请求。因此,在 HttpApplication.PostRequireRequestState 事件之前放置在 TLS 中的任何内容可能以后不会存在,因为您处于不同的线程上。
[Asker 编辑]
对于我的特定用例,我最终向 SqlException.Data 字典添加了一个键值对,在记录异常详细信息时检索该键值对。这为我提供了我希望使用线程本地存储功能的功能。

这正是我正在寻找的。我怀疑在这种情况下它可能不可靠。谢谢。 - Eric Z Beard
这是一个旧答案,但为了澄清一下:ASP.NET只在非常特定的情况下切换线程。最大的情况是使用异步IO方法 - 参见例如Lhotka和Guthrie讨论:http://www.lhotka.net/WeBlog/PermaLink,guid,019e3c37-38ed-492e-b769-16e1a57fed0a.aspx - EBarr

6

线程本地存储是一种快速修复使用了大量全局变量和静态变量的早期设计的库的方法。这是C标准库实现线程安全的方式,同时不改变其接口(内部许多函数使用静态缓冲区)。

通常情况下,它对于此目的是相当好的。如果你必须在多线程环境中使用全局数据,则线程本地存储是一个很好的选择。常见的原因是你调用一个第三方函数,在同一堆栈帧中回调,但没有提供传递额外信息的钩子 - 当你尝试在.NET中包装旧的C库时,这种情况经常发生。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接