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

时间:2021-04-01 20:04:34

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.

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

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

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.

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

3 个解决方案

#1


7  

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.

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

[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.

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

#2


6  

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).

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

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.

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

#3


0  

Have a look at new .net 4 ThreadLocal<T> class with an example, more info here.

看一下新的.net 4 ThreadLocal 类,其中包含一个示例,更多信息。

#1


7  

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.

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

[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.

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

#2


6  

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).

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

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.

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

#3


0  

Have a look at new .net 4 ThreadLocal<T> class with an example, more info here.

看一下新的.net 4 ThreadLocal 类,其中包含一个示例,更多信息。