Utilisation d'un Disons que nous avoir ce qui suit: p> Si l'ensemble du shebang soit verrouillé, comme tel: p> ou, devrait seulement L'entrée doit être gérée et lancer des «intrus», comme ça: P> System.threading.Timer (CODE> Résultats dans les threads étant filé à partir d'un
threadpool code>, ce qui signifie que si l'intervalle d'exécution pour la minuterie expire, tandis qu'un thread est toujours en traitement. Par ordre d'une demande précédente, le même rappel sera délégué pour exécuter sur un autre fil. Cela va évidemment causer des problèmes dans la plupart des cas, à moins que le rappel ne soit à nouveau conscient, mais je me demande comment em> pour y aller le meilleur (sens sûr).
private void OnOneAtATimeTimerElapsed(object state)
{
if (!RestrictOneAtATime())
{
return;
}
//get real busy for two seconds or more
if(!ReleaseOneAtATime())
{
//Well, Hell's bells and buckets of blood!
}
}
bool OneAtATimeInProgress = false;
private bool RestrictToOneAtATime()
{
bool result = false;
if (OneAtATimeLocker.TryEnterWriteLock(0))
{
if(!OneAtATimeInProgress)
{
OneAtATimeInProgress = true;
result = true;
}
OneAtATimeLocker.ExitWriteLock();
}
return result;
}
private bool ReleaseOneAtATime()
{
bool result = false;
//there shouldn't be any 'trying' about it...
if (OneAtATimeLocker.TryEnterWriteLock(0))
{
if(OneAtATimeInProgress)
{
OneAtATimeInProgress = false;
result = true;
}
OneAtATimeLocker.ExitWriteLock();
}
return result;
}
3 Réponses :
Cela dépend vraiment de si vous devez traiter chaque tick. Si vous souhaitez simplement mettre à jour certaines données périodiquement pour refléter l'état actuel des choses, vous acceptez probablement de jeter les tiques qui se produisent pendant le traitement de la traitée précédente. Si, d'autre part, vous devez traiter em> traiter chaque coche, alors vous avez un problème car dans ces cas, vous devez généralement traiter chaque tick de manière opportune.
aussi, si votre gestionnaire de tiques prend régulièrement plus de temps que l'intervalle de minuterie, alors votre intervalle de minuterie est trop courte ou que votre gestionnaire de tick doit être optimisé. Et vous courez le risque d'avoir un énorme arriéré de tiques pour traiter, ce qui signifie que quel que soit le statut que vous mise à jour est quelque peu retardé. P>
Si vous décidez de jeter des ticks qui se chevauchent (c.-à-d. Les appels entrant pendant que le La chèque précédente est traitée), je vous recommanderais d'utiliser une minuterie unique que vous réinitialisez à chaque fois après le traitement. C'est-à-dire que plutôt que de jeter des tiques empêchant de se chevaucher des tiques. P>
existe une raison particulière que vous utilisez En outre, si vous allez utiliser ReaderWriterLockSlim.grenterTritelock code> plutôt que
plutôt que code>? p>
ReaderWriterLocksLim code> ou
moniteur code>, vous devez les protéger avec
essayer .. .cinalement code>. C'est-à-dire en utilisant
moniteur code>: p>
Merci pour cette information, mais je mentionne dans d'autres commentaires que je dois réellement auditer le fait que cela se produit; Mais dans le même temps, je ne veux pas faire queue les demandes - ils peuvent être jetés, vient de noter. Mais 0 code> signifie que je m'attends à ce que le verrou soit immédiatement, afin qu'ils ne soient pas mis en file d'attente, peut-être
-1 code> attendra indéfiniment, cependant.
Beaucoup de façons de gérer cela. Un moyen simple est de ne pas fabriquer la minuterie périodique, en faire un coup unique en définissant uniquement l'argument duetime em>. Puis réactivez la minuterie dans le rappel dans un bloc enfin. Qui garantit que le rappel ne peut pas courir simultanément. P>
Ceci est bien sûr la variable d'intervalle par le temps d'exécution du rappel. Si cela n'est pas souhaitable et que le rappel ne prend que de temps en temps que la période de la minuterie, une simple serrure fera le travail. Une autre stratégie est une autre stratégie est moniteur.frenter et n'abandonnez pas le rappel s'il renvoie false. Aucun de ceux-ci n'est particulièrement supérieur, choisissez ce que vous préférez. P>
Plutôt que d'empêcher la minuterie, j'aimerais faire autre chose; nommément les entrées de journal d'écriture basées sur des occurrences. Une des choses que je suis à l'affût de ces exécutions se chevauchent. En utilisant moniteur code> pour envelopper le code concerné semble la suggestion la plus appropriée, je pense. Merci.
Je ne sais pas ce que tu veux dire, je n'ai jamais mentionné arrêter la minuterie. Utilisation de moniteur.tryenter () vous permet de connecter des chevauchements.
Désolé, je parlais de votre suggestion de minuterie unique.
BTW, y a-t-il des implications de performance notables d'aucune suggestion?
Non, acquérir une serrure n'est pas chère. Deux douzaines de nanosecondes, donnent ou prennent.
Pour un seul coup System.threading.Timer.Timer code> S est-il toujours nécessaire de verrouiller car chaque invocation pourrait / sera un fil différent?
Pour répondre à ma propre question à la recherche de la source de référence Fire () code> verrouille toujours quelque chose avant d'appeler le rappel référencesSource.microsoft.com/#mscorlib/system/threading/... . Cependant, ce n'est probablement pas une bonne idée de s'appuyer sur un détail de mise en œuvre.
Un riff légèrement différent sur le même concept, si vous n'avez pas à traiter chaque tick. Ceci est simplement des buts sur la chèque de la minuterie actuelle si vous traitez toujours une tick précédente.
private int reentrancyCount = 0; ... OnTick() { try { if (Interlocked.Increment(ref reentrancyCount) > 1) return; // Do stuff } finally { Interlocked.Decrement(ref reentrancyCount); } }
Ou vous pouvez arrêter la minuterie lors de l'entrée du gestionnaire d'événements Tick ... et réactivez à la sortie ...
Je veux que la minuterie continue de conserver des raisons d'audit, mais merci pour l'effort.
Vous voulez garder le tic-shirt pour que cela ne puisse pas travailler? C'est une exigence étrange!