J'ai développé un "pool d'objets" et n'arrive pas à le faire sans utiliser Thread.Sleep() ce qui est "une mauvaise pratique" je crois.Pool d'objets partagés sans Thread.Sleep?
Cela concerne mon autre question "Is there a standard way of implementing a proprietary connection pool in .net?". L'idée derrière le pool d'objets est similaire à celle qui se trouve derrière le pool de connexions utilisé pour les connexions à la base de données. Cependant, dans mon cas, je l'utilise pour partager une ressource limitée dans un service Web ASP.NET standard (exécuté dans IIS6). Cela signifie que de nombreux threads demanderont l'accès à cette ressource limitée. Le pool afficherait ces objets (un «Get») et une fois que tous les objets de pool disponibles auront été utilisés, le thread suivant qui en demande un attendra simplement un certain laps de temps pour qu'un de ces objets redevienne disponible (un thread ferait . un « PUT » une fois fait avec l'objet) Si un objet ne devient pas disponible dans cette période de jeu, une erreur de temporisation se produira
Voici le code:.
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);
}
}
}
Pour utiliser l'utiliser, on ferait ce qui suit:
public void ExampleUse()
{
PoolObject lTestObject = (PoolObject)SimpleObjectPool.Instance.Get();
try
{
// Do something...
}
finally
{
SimpleObjectPool.Instance.Put(lTestObject);
}
}
Maintenant la question que j'ai est: Comment est-ce que j'écris ceci pour que je me débarrasse du Thread.Sleep()?
(Pourquoi je veux faire cela parce que je pense qu'il est responsable du "faux" délai d'expiration que j'obtiens dans mes tests.Mon application de test a un pool d'objets avec 3 objets dedans. et chaque thread obtient 100 fois un objet du pool.Si le thread obtient un objet du pool, il le conserve si pendant 2000 ms, si ce n'est pas le cas, il passe à l'itération suivante. attendre 9 x 2 000 ms est 18 000 ms, ce qui est le temps maximum que chaque thread doit attendre pour un objet.Le délai d'attente de mon get est fixé à 60 000 ms, donc aucun thread ne doit jamais être temporisé. faites donc quelque chose qui ne va pas et je soupçonne que c'est le Thread.Sleep)
Plusieurs lecteurs d'une seule ressource partagée sonne comme un sémaphore. Pourquoi ne l'utilisez-vous pas? – Amirshk
D'autres ont répondu à ce que vous devriez faire. Je vais juste commenter pourquoi Sleep() est une mauvaise idée à utiliser ici - il n'y a rien qui vous garantit que lorsque le thread se réveille, il y aura un objet dans le pool. Ainsi, avec un peu de «chance», un thread peut continuer à dormir pendant que d'autres threads choisissent les objets regroupés. Ce dont vous avez besoin, c'est d'un mécanisme d'attente qui réveillera le fil lorsqu'un objet deviendra disponible. –