2011-10-18 3 views
4

Dans une application Silverlight, j'ai un bloc de code qui doit s'exécuter toutes les 500ms. Je prévois d'utiliser un DispatcherTimer pour y parvenir (voir le code ci-dessous).DispatchTimer - Empêche le déclenchement de l'événement tick si le tick précédent est toujours en cours

DispatcherTimer dt = new DispatcherTimer(); 
dt.Interval = new TimeSpan(0, 0, 0, 0, 500); // 500 Milliseconds 
dt.Tick += new EventHandler(dt_Tick); 
dt.Start(); 

Cependant, il peut arriver que le bloc de code prend plus de 500 ms pour exécuter (le bloc de code fait quelques appels WebService). Comment puis-je m'assurer que si un appel est en cours, le DispatcherTimer ne déclenche pas un autre événement? Quelles sont les options et quelle est la meilleure façon? À l'aide de verrous?

Répondre

1

Je dirais que vous omettez une coche si cela prend trop de temps, sinon vous aurez une énorme file d'attente à cause du verrou.

Ainsi, dans le eventhandler disent:

if(!busy) { 
    busy = true; 

    // some code which could take longer than 500 ms 

    busy = false; 
} 
1

Je ne sais pas si DispatchTimer a une façon intelligente de le faire, mais ce que je ferais dans cette situation est de ne pas essayer d'obtenir la minuterie de ne pas tirer l'événement mais pour que l'événement ne fasse rien s'il n'a pas fini la course précédente.

Vous pouvez utiliser des verrous pour cela en obtenant un verrou au début de votre gestionnaire d'événements. Si le verrou n'est pas disponible, alors quittez la fonction (c'est déjà en cours) si vous avez le verrou faire le travail et une fois que vous avez terminé le travail, relâchez le verrou.

La méthode que vous voulez est Monitor.TryEnter et vous voudrez vous assurer que vous faites votre piégeage d'erreur correctement comme avec toute utilisation de verrous.

1

Pour rendre l'événement courir Successfull sans avoir reçu un appel de votre DispatcherTimer à nouveau avec la tique précédente termine stop la minuterie répartiteur après l'entrée pour l'événement dt_Tick et à la fin de l'événement tick appeler à nouveau la start qui Initialise le IsEnabled de DispatcherTimer à nouveau à true.

4

Le DispatcherTimerseulement s'exécute sur le thread Dispatcher - il est donc impossible d'avoir deux gestionnaires en cours d'exécution en même temps. Il est possible qu'ils soient mis en file d'attente et qu'ils courent l'un après l'autre, bien sûr - vous devriez vérifier.

Cependant, ne devrait pas faire un appel de service Web dans un DispatcherTimer de toute façon. Faites-le dans un thread d'arrière-plan, sinon vous bloquez l'interface utilisateur pour mettre à jour tout le temps que vous attendez le service Web. Fondamentalement, vous ne devriez pas faire un travail de longue durée dans le thread de l'interface utilisateur. Utilisez l'un des divers autres temporisateurs (par exemple, System.Timers.Timer) pour effectuer régulièrement des tâches sur un thread de pool de threads et utilisez le répartiteur pour rappeler le thread de l'interface utilisateur lorsque vous avez des données devant être affichées sur l'interface utilisateur.

Bien sûr, vous avez maintenant le problème potentiel du nouveau type de temporisation qui se déclenche plusieurs fois simultanément, sur plusieurs threads. Une option pour éviter cela est de définir la propriété AutoReset sur false, et de programmer la coche de la minuterie suivante à la fin de la propriété actuelle.

+0

J'ai oublié de mentionner que j'utilise Silverlight pour Windows Phone. Je ne trouve pas System.Timers.Timer. – Martin

+0

@Martin: D'accord, utilisez plutôt System.Threading.Timer. Même principe de base :) –

+0

Une dernière question Jon. Si j'utilise le System.Timers.Timer, est-il possible que deux événements tick puissent être exécutés en même temps? – Martin

Questions connexes