在查看 System.ServiceModel.Channels.BufferManager 的源代码时,我注意到了这个方法:
void TuneQuotas()
{
if (areQuotasBeingTuned)
return;
bool lockHeld = false;
try
{
try { }
finally
{
lockHeld = Monitor.TryEnter(tuningLock);
}
// Don't bother if another thread already has the lock
if (!lockHeld || areQuotasBeingTuned)
return;
areQuotasBeingTuned = true;
}
finally
{
if (lockHeld)
{
Monitor.Exit(tuningLock);
}
}
//
// DO WORK... (code removed for brevity)
//
areQuotasBeingTuned = false;
}
显然,他们只希望一个线程运行TuneQuotas()
,如果它已经被另一个线程运行,则其他线程不等待。我应该注意,删除的代码没有尝试保护。
我试图了解上述这种方法的优势,而不是仅仅这样做:
void TuneQuotas()
{
if(!Monitor.TryEnter(tuningLock)) return;
//
// DO WORK...
//
Monitor.Exit(tuningLock);
}
任何想法为什么他们可能会为这一切而烦恼?我怀疑他们使用这些finally
块的方式是为了防止线程中止情况,但我仍然不明白这一点,因为即使有所有这些代码,如果那个线程不能全部完成,TuneQuotas()
也会被永久锁定设置结束的方式areQuotasBeingTunes=false
,出于某种原因。那么我错过了这种模式有什么很酷的地方吗?
编辑: 作为旁注,该方法似乎存在于 .NET 4.0 中,我使用在框架 4 上运行的此代码确认了这一点(尽管我无法确认该方法的内容与我在网上找到的内容没有改变) :
var buffMgr = BufferManager.CreateBufferManager(1, 1);
var pooledBuffMgrType = buffMgr.GetType()
.GetProperty("InternalBufferManager")
.GetValue(buffMgr, null)
.GetType();
Debug.WriteLine(pooledBuffMgrType.Module.FullyQualifiedName);
foreach (var methodInfo in pooledBuffMgrType
.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic))
{
Debug.WriteLine(methodInfo.Name);
}
输出:
C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Runtime.DurableInstancing\v4.0_4.0.0.0__3 1bf3856ad364e35\System.Runtime.DurableInstancing.dll
ChangeQuota
DecreaseQuota
FindMostExcessivePool
FindMostStarvedPool
FindPool
IncreaseQuota
TuneQuotas
Finalize
MemberwiseClone