派生类型与静态信号量一起用作基类中的类型参数,以在每个子类的所有实例之间共享一个信号量。然后有一些混乱,以确保只有一种类型处于活动状态。快速测试表明这可以正常工作,但存在问题。
例如假设ClassA1
当前正在执行的方法。如果执行此方法的新请求以很高的频率到达,则可能会发生其他派生类没有机会执行的情况,因为不断有新线程执行该类的方法ClassA1
。
internal abstract class ClassA<TDerived> : ClassA
{
private const Int32 MaximumNumberConcurrentThreads = 3;
private static readonly Semaphore semaphore = new Semaphore(ClassA<TDerived>.MaximumNumberConcurrentThreads, ClassA<TDerived>.MaximumNumberConcurrentThreads);
internal void MethodA()
{
lock (ClassA.setCurrentlyExcutingTypeLock)
{
while (!((ClassA.currentlyExcutingType == null) || (ClassA.currentlyExcutingType == typeof(TDerived))))
{
Monitor.Wait(ClassA.setCurrentlyExcutingTypeLock);
}
if (ClassA.currentlyExcutingType == null)
{
ClassA.currentlyExcutingType = typeof(TDerived);
}
ClassA.numberCurrentlyPossiblyExecutingThreads++;
Monitor.PulseAll(ClassA.setCurrentlyExcutingTypeLock);
}
try
{
ClassA<TDerived>.semaphore.WaitOne();
this.MethodACore();
}
finally
{
ClassA<TDerived>.semaphore.Release();
}
lock (ClassA.setCurrentlyExcutingTypeLock)
{
ClassA.numberCurrentlyPossiblyExecutingThreads--;
if (ClassA.numberCurrentlyPossiblyExecutingThreads == 0)
{
ClassA.currentlyExcutingType = null;
Monitor.Pulse(ClassA.setCurrentlyExcutingTypeLock);
}
}
}
protected abstract void MethodACore();
}
请注意,包装器方法用于调用MethodACore
. 所有派生类之间共享的所有同步对象都在非泛型基类中。
internal abstract class ClassA
{
protected static Type currentlyExcutingType = null;
protected static readonly Object setCurrentlyExcutingTypeLock = new Object();
protected static Int32 numberCurrentlyPossiblyExecutingThreads = 0;
}
派生类将如下所示。
internal sealed class ClassA1 : ClassA<ClassA1>
{
protected override void MethodACore()
{
// Do work here.
}
}
internal sealed class ClassA2 : ClassA<ClassA2>
{
protected override void MethodACore()
{
// Do work here.
}
}
不幸的是,我现在没有时间更详细地解释它是如何以及为什么起作用的,但我明天会更新答案。