Juste ceci - Comment ajouter une minuterie à une application console C #? Ce serait formidable si vous pouviez fournir un exemple de codage.
C'est très agréable, mais pour simuler un certain temps, nous devons exécuter une commande qui prend un certain temps et qui est très claire dans le deuxième exemple.
Cependant, le style d'utilisation d'une boucle for pour certaines fonctionnalités nécessite des ressources de périphérique considérables. Nous pouvons utiliser le collecteur de place pour procéder de la sorte.
Nous pouvons voir cette modification dans le code du même livre CLR Via C # Third Ed.
using System;
using System.Threading;
public static class Program {
public static void Main() {
// Create a Timer object that knows to call our TimerCallback
// method once every 2000 milliseconds.
Timer t = new Timer(TimerCallback, null, 0, 2000);
// Wait for the user to hit <Enter>
Console.ReadLine();
}
private static void TimerCallback(Object o) {
// Display the date/time when this method got called.
Console.WriteLine("In TimerCallback: " + DateTime.Now);
// Force a garbage collection to occur for this demo.
GC.Collect();
}
}
Utilisez la classe System.Threading.Timer.
System.Windows.Forms.Timer est conçu principalement pour être utilisé dans un seul thread, généralement le thread d'interface utilisateur Windows Forms.
Une classe System.Timers a également été ajoutée au début du développement du framework .NET. Cependant, il est généralement recommandé d'utiliser la classe System.Threading.Timer, car il ne s'agit en tout cas que d'une enveloppe autour de System.Threading.Timer.
Il est également recommandé de toujours utiliser un System.Threading.Timer statique (partagé dans VB.NET) si vous développez un service Windows et que vous devez exécuter un minuteur à intervalles réguliers. Cela évitera peut-être une récupération de mémoire prématurée de votre objet timer.
Voici un exemple de minuterie dans une application console:
using System;
using System.Threading;
public static class Program
{
public static void Main()
{
Console.WriteLine("Main thread: starting a timer");
Timer t = new Timer(ComputeBoundOp, 5, 0, 2000);
Console.WriteLine("Main thread: Doing other work here...");
Thread.Sleep(10000); // Simulating other work (10 seconds)
t.Dispose(); // Cancel the timer now
}
// This method's signature must match the TimerCallback delegate
private static void ComputeBoundOp(Object state)
{
// This method is executed by a thread pool thread
Console.WriteLine("In ComputeBoundOp: state={0}", state);
Thread.Sleep(1000); // Simulates other work (1 second)
// When this method returns, the thread goes back
// to the pool and waits for another task
}
}
Extrait du livre CLR Via C # par Jeff Richter. En passant, ce livre décrit la raison d'être fortement recommandée des 3 types de minuteries du chapitre 23.
Voici le code pour créer une simple tic-ture d'une seconde:
using System;
using System.Threading;
class TimerExample
{
static public void Tick(Object stateInfo)
{
Console.WriteLine("Tick: {0}", DateTime.Now.ToString("h:mm:ss"));
}
static void Main()
{
TimerCallback callback = new TimerCallback(Tick);
Console.WriteLine("Creating timer: {0}\n",
DateTime.Now.ToString("h:mm:ss"));
// create a one second timer tick
Timer stateTimer = new Timer(callback, null, 0, 1000);
// loop here forever
for (; ; )
{
// add a sleep for 100 mSec to reduce CPU usage
Thread.Sleep(100);
}
}
}
Et voici le résultat obtenu:
c:\temp>timer.exe
Creating timer: 5:22:40
Tick: 5:22:40
Tick: 5:22:41
Tick: 5:22:42
Tick: 5:22:43
Tick: 5:22:44
Tick: 5:22:45
Tick: 5:22:46
Tick: 5:22:47
EDIT: Ce n'est jamais une bonne idée d'ajouter des boucles de spin dur dans le code car elles consomment des cycles de la CPU sans gain. Dans ce cas, cette boucle a été ajoutée simplement pour empêcher la fermeture de l'application, permettant ainsi d'observer les actions du thread. Mais dans un souci d'exactitude et de réduction de l'utilisation du processeur, un simple appel de veille a été ajouté à cette boucle.
Permet de s'amuser un peu
using System;
using System.Timers;
namespace TimerExample
{
class Program
{
static Timer timer = new Timer(1000);
static int i = 10;
static void Main(string[] args)
{
timer.Elapsed+=timer_Elapsed;
timer.Start();
Console.Read();
}
private static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
i--;
Console.Clear();
Console.WriteLine("=================================================");
Console.WriteLine(" DIFFUSE THE BOMB");
Console.WriteLine("");
Console.WriteLine(" Time Remaining: " + i.ToString());
Console.WriteLine("");
Console.WriteLine("=================================================");
if (i == 0)
{
Console.Clear();
Console.WriteLine("");
Console.WriteLine("==============================================");
Console.WriteLine(" B O O O O O M M M M M ! ! ! !");
Console.WriteLine("");
Console.WriteLine(" G A M E O V E R");
Console.WriteLine("==============================================");
timer.Close();
timer.Dispose();
}
GC.Collect();
}
}
}
Ou en utilisant Rx, court et doux:
static void Main()
{
Observable.Interval(TimeSpan.FromSeconds(10)).Subscribe(t => Console.WriteLine("I am called... {0}", t));
for (; ; ) { }
}
Vous pouvez également utiliser vos propres mécanismes de minutage si vous voulez un peu plus de contrôle, mais peut-être moins de précision et davantage de code/complexité, mais je recommanderais quand même un minuteur. Utilisez ceci si vous avez besoin de contrôler le fil de synchronisation actuel:
private void ThreadLoop(object callback)
{
while(true)
{
((Delegate) callback).DynamicInvoke(null);
Thread.Sleep(5000);
}
}
serait votre fil de chronométrage (modifiez ceci pour qu’il s’arrête quand vous le souhaitez, et à l’intervalle de temps que vous souhaitez).
et pour utiliser/commencer vous pouvez faire:
Thread t = new Thread(new ParameterizedThreadStart(ThreadLoop));
t.Start((Action)CallBack);
Le rappel est votre méthode vide, sans paramètre, que vous souhaitez appeler à chaque intervalle. Par exemple:
private void CallBack()
{
//Do Something.
}
Vous pouvez également créer le vôtre (si vous n'êtes pas satisfait des options disponibles).
Créer votre propre implémentation Timer
est assez simple.
Voici un exemple d'application qui nécessitait un accès à un objet COM sur le même thread que le reste de ma base de code.
/// <summary>
/// Internal timer for window.setTimeout() and window.setInterval().
/// This is to ensure that async calls always run on the same thread.
/// </summary>
public class Timer : IDisposable {
public void Tick()
{
if (Enabled && Environment.TickCount >= nextTick)
{
Callback.Invoke(this, null);
nextTick = Environment.TickCount + Interval;
}
}
private int nextTick = 0;
public void Start()
{
this.Enabled = true;
Interval = interval;
}
public void Stop()
{
this.Enabled = false;
}
public event EventHandler Callback;
public bool Enabled = false;
private int interval = 1000;
public int Interval
{
get { return interval; }
set { interval = value; nextTick = Environment.TickCount + interval; }
}
public void Dispose()
{
this.Callback = null;
this.Stop();
}
}
Vous pouvez ajouter des événements comme suit:
Timer timer = new Timer();
timer.Callback += delegate
{
if (once) { timer.Enabled = false; }
Callback.execute(callbackId, args);
};
timer.Enabled = true;
timer.Interval = ms;
timer.Start();
Window.timers.Add(Environment.TickCount, timer);
Pour vous assurer que le minuteur fonctionne, vous devez créer une boucle sans fin comme suit:
while (true) {
// Create a new list in case a new timer
// is added/removed during a callback.
foreach (Timer timer in new List<Timer>(timers.Values))
{
timer.Tick();
}
}