我已经开发了一个“对象池”,如果不使用 Thread.Sleep() 似乎无法做到这一点,我认为这是“不好的做法”。
这与我的另一个问题“是否有在.net 中实现专有连接池的标准方法? ”有关。对象池背后的想法类似于用于数据库连接的连接池背后的想法。但是,就我而言,我使用它来共享标准 ASP.NET Web 服务(在 IIS6 中运行)中的有限资源。这意味着许多线程将请求访问此有限资源。池将抛出这些对象(“获取”),一旦所有可用的池对象都被使用,下一个请求的线程将简单地等待一段时间,以使这些对象中的一个再次可用(线程会这样做一次“放置”对象)。如果对象在此设定时间内不可用,则会发生超时错误。
这是代码:
public class SimpleObjectPool
{
private const int cMaxGetTimeToWaitInMs = 60000;
private const int cMaxGetSleepWaitInMs = 10;
private object fSyncRoot = new object();
private Queue<object> fQueue = new Queue<object>();
private SimpleObjectPool()
{
}
private static readonly SimpleObjectPool instance = new SimpleObjectPool();
public static SimpleObjectPool Instance
{
get
{
return instance;
}
}
public object Get()
{
object aObject = null;
for (int i = 0; i < (cMaxGetTimeToWaitInMs / cMaxGetSleepWaitInMs); i++)
{
lock (fSyncRoot)
{
if (fQueue.Count > 0)
{
aObject = fQueue.Dequeue();
break;
}
}
System.Threading.Thread.Sleep(cMaxGetSleepWaitInMs);
}
if (aObject == null)
throw new Exception("Timout on waiting for object from pool");
return aObject;
}
public void Put(object aObject)
{
lock (fSyncRoot)
{
fQueue.Enqueue(aObject);
}
}
}
要使用它,可以执行以下操作:
public void ExampleUse()
{
PoolObject lTestObject = (PoolObject)SimpleObjectPool.Instance.Get();
try
{
// Do something...
}
finally
{
SimpleObjectPool.Instance.Put(lTestObject);
}
}
现在我的问题是:我该如何写才能摆脱 Thread.Sleep()?
(我为什么要这样做是因为我怀疑它是导致我在测试中遇到的“错误”超时的原因。我的测试应用程序有一个对象池,其中包含 3 个对象。它启动 12 个线程,每个线程得到从池中获取对象 100 次。如果线程从池中获取对象,它将保持 if 2,000 毫秒,如果没有,则进入下一次迭代。现在逻辑表明 9 个线程将等待对象在任何时间点。9 x 2,000 毫秒是 18,000 毫秒,这是任何线程应该等待对象的最长时间。我的获取超时设置为 60,000 毫秒,因此任何线程都不应该超时。但是有些这样做是错了,我怀疑它是 Thread.Sleep)