2010-10-14 14 views
0

J'ai un problème un peu maladroit, je travaille avec C# et WPF dans .NET 4.0 et ce dont j'ai besoin est un minuteur qui va créer un seul thread, mais il faudra travailler dans l'arrière-plan, donc pas dans le thread principal, le problème utilise System.Windows.Forms.Timer ou DispatchTimer l'obligera automatiquement à travailler sur le thread principal et être influencé par l'interface utilisateur, de l'autre côté en utilisant System.Timers.Timer ou System.Threading.Timer va créer un nouveau thread pour chaque cycle qui dépasse l'intervalle de temps, cela arrivera puisque le code dans l'événement timer écoulé est un peu gros, bien qu'une partie de celui-ci soit envoyée plus loin à un worker d'arrière-plan.minuterie de fond ne travaillant que dans un thread C#

donc je pensais s'il est possible de forcer, dire System.Timers.Timer, travailler en arrière-plan et de ne jamais se reproduire à plus d'un fil, aussi je suis ouvert à d'autres suggestions

+1

Que voulez-vous arriver si la prochaine tique se produit alors que le cycle actuel est encore en cours de traitement? – Justin

+0

Et qu'est-ce que vous essayez d'accomplir avec le fil de fond? Est-ce juste quelque chose qui doit être en cours d'exécution, et le minuteur doit s'assurer que le fil existe? –

+0

@justin: Je veux attendre pendant que le cycle en cours se termine traitement – WarBorg

Répondre

1

Utilisez System.Timers.Timer, qui déclenche son gestionnaire d'événements écoulé sur un thread ThreadPool. Dès que vous entrez dans le gestionnaire d'événements, arrêtez la minuterie. À la fin de votre gestionnaire d'événements, démarrez le chronomètre et il commencera à compter à partir du début de son intervalle.

Voici un exemple simple avec une minuterie 100ms qui passe 2 secondes dans son gestionnaire d'événements: ÉCOULÉ

static void Main(string[] args) 
{ 
    System.Timers.Timer myTimer = new System.Timers.Timer(100); 
    myTimer.Elapsed += new System.Timers.ElapsedEventHandler(myTimer_Elapsed); 
    myTimer.Start(); 
    Console.ReadLine(); 
} 

static void myTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 
{ 
    ((System.Timers.Timer)sender).Stop(); 
    Console.WriteLine(DateTime.Now.ToString("HH.mm.ss")); 
    System.Threading.Thread.Sleep(2000); 
    ((System.Timers.Timer)sender).Start(); 
} 
+0

oui, merci , qui semble le moyen le plus facile d'obtenir ce dont j'ai besoin – WarBorg

+0

System.Threading.Timer s'exécute également dans le thread ThreadPool avec l'avantage de ne pas avoir à le réinitialiser sur chaque événement Elapsed. –

1

Il suffit d'utiliser un System.Threading.Timer avec une période de 0 pour que le rappel ne s'exécute qu'une seule fois. Lorsque tout est terminé, rechargez la minuterie afin qu'elle se déclenche plus tard. Vous aurez garanti seulement un fil de discussion de cette façon.

1

DispatcherTimer a une surcharge de constructeur qui vous permet de faire exactement ce que vous voulez. Utilisez-le dans le contexte de votre fil:

using System.Threading; 
using WpfThreading = System.Windows.Threading; 

... 

Thread t = new Thread(() => 
{ 
    var interval = TimeSpan.FromSeconds(3.0); 
    var priority = WpfThreading.DispatcherPriority.Background; 
    EventHandler callback = (a, e) => { }; 
    var dispatcher = WpfThreading.Dispatcher.CurrentDispatcher; // dispatcher for this thread 
    WpfThreading.DispatcherTimer dt = new WpfThreading.DispatcherTimer(interval, priority, callback, dispatcher); 

    bool sameDispatchers = WpfThreading.Dispatcher.CurrentDispatcher == this.Dispatcher; // false 
}); 
t.Start();