没有Thread.Sleep的共享对象池?

Vin*_*eJS 2 .net c# multithreading sleep pooling

我已经开发了一个"对象池",如果不使用Thread.Sleep()这似乎是不行的,这是我认为的"坏习惯".

这与我的另一个问题" 是否存在在.net中实现专有连接池的标准方法 "有关.对象池背后的想法类似于用于数据库连接的连接池背后的想法.但是,在我的情况下,我使用它来共享标准ASP.NET Web服务(在IIS6中运行)中的有限资源.这意味着许多线程将请求访问此有限资源.池会抛出这些对象("Get"),一旦使用了所有可用的池对象,下一个请求一个的线程就会等待一段时间让这些对象中的一个再次可用(一个线程可以做)一旦对象完成"放置".如果对象在此设置时间内不可用,则会发生超时错误.

这是代码:

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

要使用它,可以执行以下操作:

        public void ExampleUse()
        {
            PoolObject lTestObject = (PoolObject)SimpleObjectPool.Instance.Get();
            try
            {
                // Do something...
            }
            finally
            {
                SimpleObjectPool.Instance.Put(lTestObject);
            }
        }
Run Code Online (Sandbox Code Playgroud)

现在我的问题是:我如何写这个,所以我摆脱了Thread.Sleep()?

(为什么我要这样做是因为我怀疑它是我在测试中得到的"错误"超时的原因.我的测试应用程序有一个包含3个对象的对象池.它旋转了12个线程,每个线程得到池中的一个对象100次.如果线程从池中获取一个对象,它会持续到2000毫秒,如果没有,则进入下一次迭代.现在逻辑指示9个线程将等待一个在任何时间点对象.9 x 2,000 ms是18,000 ms,这是任何线程等待对象所需的最长时间.我的获取超时设置为60,000 ms,因此没有线程应该超时.但是有些事情是这样的错了,我怀疑它的Thread.Sleep)

Hen*_*man 5

由于您已经在使用lock,请考虑使用Monitor.WaitMonitor.Pulse

Get():

lock (fSyncRoot)
{
   while (fQueue.Count < 1)
     Monitor.Wait(fSyncRoot);

   aObject = fQueue.Dequeue();
}
Run Code Online (Sandbox Code Playgroud)

并在Put():

lock (fSyncRoot)
{
   fQueue.Enqueue(aObject);
   if (fQueue.Count == 1)
         Monitor.Pulse(fSyncRoot);
}
Run Code Online (Sandbox Code Playgroud)