在 .NET 中使用线程本地存储的最佳实践是什么?
我的应用程序中有一个要求,我认为可以通过使用线程本地存储来满足,但我想知道这是否是最好避免的事情之一。
我读过一些关于该主题的文章:
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”之类的东西的好地方,但这看起来不是一个可行的解决方案。
I have a requirement in my application that I think can be met by using thread local storage, but I'm wondering if it's one of those things that's best to avoid.
I have read a few articles on the subject:
http://www.dotnetcoders.com/web/Articles/ShowArticle.aspx?article=58
http://msdn.microsoft.com/en-us/library/system.threadstaticattribute(vs.80).aspx
I know how to use it, I'm just wondering if I should use it.
Any advice, gotchas to be aware of?
[Edit]
Here's the use case:
I funnel all data access through a few methods that do a lot of logging about each query. One thing I log is a complete dump of the command text with commands filled in so that I can simply copy-paste from my trace logs directly into Sql Management Studio.
Way up in global.asax in my web apps I send email to admins with as much information as I can when I get an unhandled exception. I want to put that sql command dump text into this email when I get a SqlException, which will save me the time of digging through trace logs when a page blows up because of a query.
I don't want to change the method signatures of my data access classes just so I can pass some reference all the way down the stack, just to get it out when I get an exception. I was thinking maybe TLS would be a good place to put something like "lastsqlcommand", but that's not looking like a viable solution.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
ASP.NET 应用程序的一个陷阱:单个请求的处理可能会切换线程,即同一会话中存在并行请求时。 因此,您在 HttpApplication.PostRequireRequestState 事件之前放入 TLS 中的任何内容稍后可能不会出现,因为您位于不同的线程上。
[由询问者编辑]
对于我的特定用例,我最终向 SqlException.Data 字典添加了一个键值对,然后在记录异常详细信息时检索该字典。 这为我提供了我希望使用线程本地存储的功能。
A gotcha for asp.net applications: the processing of a single request might switch threads, namely if there are parallel requests in the same session. Because of this, anything you put in TLS before the HttpApplication.PostRequireRequestState event might not be there later, because you are on a different thread.
[Edit by the asker]
For my particular use case, I ended up adding a key-value pair to the SqlException.Data dictionary, which I then retrieve when I log the exception details. This gives me the functionality I was hoping to use thread local storage for.
线程本地存储是修复在线程之前设计并使用大量全局变量和静态的库的快速方法。 这是 C 标准库在不更改其接口的情况下实现线程安全的方式(在内部,许多函数使用静态缓冲区)。
一般来说,这对于这个目的来说是有好处的。 如果您必须在多线程环境中拥有全局数据,那么线程本地存储是一个不错的选择。 一个常见的原因是您正在调用一个第三方函数,该函数会在同一个堆栈帧中回调您,但不会为您提供传递额外信息的钩子——当您尝试将旧的 C 库包装在其中时,这种情况经常发生。 。网。
Thread local storage is a quick way to fix a library that was designed before threads and uses a lot of global variables and statics. It's the way that the C standard library was made thread-safe while not changing its interface (internally, many functions use static buffers).
Generally, it's kind of good for that purpose. If you have to have global data in a multi-threaded environment, then thread-local storage is a good way to go. A common reason is that you are calling a third-party function that calls you back in the same stack-frame but doesn't give you a hook for passing extra information -- this happens a lot when you try to wrap older C libraries in .NET.
查看新的 .net 4 ThreadLocal 类,其中包含例如,更多信息
Have a look at new .net 4 ThreadLocal<T> class with an example, more info here.