Я разработал «пул объектов» и, похоже, не могу сделать это без использования Thread.Sleep (), что, по моему мнению, является «плохой практикой».
Это относится к моему другому вопросу " Существует ли стандартный способ реализации проприетарного пула соединений в .net? ". Идея, лежащая в основе пула объектов, аналогична идее позади пула соединений, используемой для соединений с базой данных. Однако в моем случае я использую его для совместного использования ограниченного ресурса в стандартной веб-службе ASP.NET (запущенной в 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);
}
}
}
Чтобы использовать его, нужно сделать следующее:
public void ExampleUse()
{
PoolObject lTestObject = (PoolObject)SimpleObjectPool.Instance.Get();
try
{
// Do something...
}
finally
{
SimpleObjectPool.Instance.Put(lTestObject);
}
}
Теперь у меня вопрос: как мне написать это, чтобы избавиться от Thread.Sleep ()?
(Почему я хочу сделать это, потому что я подозреваю, что он ответственен за «ложный» тайм-аут, который я получаю в своем тестировании. У моего тестового приложения есть пул объектов с 3 объектами в нем. Он раскручивает 12 потоков и каждый поток получает объект из пула 100 раз. Если поток получает объект из пула, он удерживается, если в течение 2000 мс, если нет, он переходит к следующей итерации. Теперь логика диктует, что 9 потоков будут ожидание объекта в любой момент времени. 9 x 2000 мс - это 18 000 мс, что является максимальным временем, в течение которого поток должен ждать объект. Мой тайм-аут для получения установлен равным 60 000 мс, поэтому ни один поток никогда не должен останавливаться. Однако некоторые так что-то не так, и я подозреваю, что это Thread.Sleep)