ASP.NET 和 ThreadStatic 作为 TransactionScope 实现的一部分
我想知道 TransactionScope 类如何工作来保持不同方法调用之间的事务(不需要将其作为参数传递),我对此产生了疑问。关于这个问题,我有两个考虑:
1
通过 Telerik JustDecompile 查看 TransactionScope 的实现,我发现当前事务存储在 System.Transactions.ContextData 类的 ThreadStatic 成员中(代码如下)。
internal class ContextData
{
internal TransactionScope CurrentScope;
internal Transaction CurrentTransaction;
internal DefaultComContextState DefaultComContextState;
[ThreadStatic]
private static ContextData staticData;
internal WeakReference WeakDefaultComContext;
internal static ContextData CurrentData
{
get
{
ContextData contextDatum = ContextData.staticData;
if (contextDatum == null)
{
contextDatum = new ContextData();
ContextData.staticData = contextDatum;
}
return contextDatum;
}
}
public ContextData()
{
}
}
CurrentData 属性由 TransactionScope 的 PushScope() 方法调用,最后一个属性被大多数 TransactionScope 构造函数使用。
private void PushScope()
{
if (!this.interopModeSpecified)
{
this.interopOption = Transaction.InteropMode(this.savedCurrentScope);
}
this.SetCurrent(this.expectedCurrent);
this.threadContextData.CurrentScope = this;
}
public TransactionScope(TransactionScopeOption scopeOption)
{
// ...
this.PushScope();
// ...
}
好吧,我想我已经找到他们是怎么做到的了。
2
我读过有关使用 ThreadStatic 成员在 ASP.NET 中存储对象有多么糟糕(http://www.hanselman.com/blog/ATaleOfTwoTechniquesTheThreadStaticAttributeAndSystemWebHttpContextCurrentItems.aspx),因为可能会发生 ASP.NET 线程切换,所以这工作线程之间的数据可能会丢失。
那么,看起来 TransactionScope 不应该与 ASP.NET 一起使用,对吗?但就我在网络应用程序上使用它而言,我不记得遇到过任何有关交易数据丢失的问题。
我的问题是“TransactionScope 处理 ASP.NET 线程切换的技巧是什么?”。
我是否对TransactionScope如何存储其事务对象进行了粗浅的分析?或者 TransactionScope 类不是为与 ASP.NET 一起工作而设计的,我可以被认为是一个幸运的人,从来没有遇到过任何痛苦?
任何知道 .NET“深藏的秘密”的人都可以为我解释一下吗?
谢谢
I was wondering how TransactionScope class works to keep the transaction between different method calls (without the need to pass it as a parameter) and I came to this doubt. I've got two considerations about this question:
1
Looking into TransactionScope's implementation through Telerik JustDecompile, I've found that the current transaction is stored in a ThreadStatic member of the System.Transactions.ContextData class (code below).
internal class ContextData
{
internal TransactionScope CurrentScope;
internal Transaction CurrentTransaction;
internal DefaultComContextState DefaultComContextState;
[ThreadStatic]
private static ContextData staticData;
internal WeakReference WeakDefaultComContext;
internal static ContextData CurrentData
{
get
{
ContextData contextDatum = ContextData.staticData;
if (contextDatum == null)
{
contextDatum = new ContextData();
ContextData.staticData = contextDatum;
}
return contextDatum;
}
}
public ContextData()
{
}
}
The CurrentData property is called by TransactionScope's PushScope() method, and the last one is used by most of the TransactionScope constructors.
private void PushScope()
{
if (!this.interopModeSpecified)
{
this.interopOption = Transaction.InteropMode(this.savedCurrentScope);
}
this.SetCurrent(this.expectedCurrent);
this.threadContextData.CurrentScope = this;
}
public TransactionScope(TransactionScopeOption scopeOption)
{
// ...
this.PushScope();
// ...
}
Ok, I guess I've found how they do that.
2
I've read about how bad is to use ThreadStatic members to store objects within ASP.NET (http://www.hanselman.com/blog/ATaleOfTwoTechniquesTheThreadStaticAttributeAndSystemWebHttpContextCurrentItems.aspx) due the ASP.NET thread switching that might occur, so this data can be lost among the worker threads.
So, it looks like TransactionScope should not work with ASP.NET, right? But as far I have used it on my web applications, I don't remember any problem that I've run into about transaction data being lost.
My question here is "what's the TransactionScope's trick to deal with ASP.NET's thread switching?".
Did I make a superficial analysis on how TransactionScope stores its transaction objects? Or TransactionScope class wasn't made to work with ASP.NET, and I can be considered a lucky guy that never had any pain about it?
Could anyone who knows the "very deep buried secrets" of .NET explain that for me?
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我相信 ASP.NET 线程切换仅发生在特定情况(涉及异步 IO 操作)和请求生命周期的早期。通常,一旦控制权传递到实际的 http 处理程序(例如 Page),线程就不会切换。我相信在大多数情况下,事务范围只会在那之后(在 page_init/load 之后)初始化,并且不应该成为问题。
以下是您可能感兴趣的一些链接:
http://piers7.blogspot。 com/2005/11/threadstatic-callcontext-and_02.html
http://piers7.blogspot.com/2005/12/log4net -context-problems-with-aspnet.html
I believe ASP.NET thread switching happens only in specific situations (involving asych IO operations) and early in the request life cycle. Typically, once the control is passed to the actual http handler (for example, Page), thread does not get switched. I believe that in most of situation, transaction scope will get initialized only after that (after page_init/load) and should not be an issue.
Here are few links that might interest you:
http://piers7.blogspot.com/2005/11/threadstatic-callcontext-and_02.html
http://piers7.blogspot.com/2005/12/log4net-context-problems-with-aspnet.html