Solo questo: come si aggiunge un timer a un'applicazione console C #? Sarebbe bello se potessi fornire alcuni esempi di codifica.
Solo questo: come si aggiunge un timer a un'applicazione console C #? Sarebbe bello se potessi fornire alcuni esempi di codifica.
Risposte:
È molto carino, tuttavia per simulare il passare del tempo è necessario eseguire un comando che richiede del tempo ed è molto chiaro nel secondo esempio.
Tuttavia, lo stile di utilizzo di un ciclo for per eseguire alcune funzionalità richiede per sempre molte risorse del dispositivo e invece possiamo usare Garbage Collector per fare qualcosa del genere.
Possiamo vedere questa modifica nel codice dallo stesso libro 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();
}
}
GC.Collect()
. Non c'è niente da collezionare. Avrebbe senso, se GC.KeepAlive(t)
fosse stato chiamato dopoConsole.ReadLine();
Utilizzare la classe System.Threading.Timer.
System.Windows.Forms.Timer è progettato principalmente per l'uso in un singolo thread, in genere il thread dell'interfaccia utente di Windows Form.
Esiste anche una classe System.Timers aggiunta all'inizio dello sviluppo del framework .NET. Tuttavia, in genere si consiglia di utilizzare la classe System.Threading.Timer, poiché si tratta comunque solo di un wrapper per System.Threading.Timer.
Si consiglia inoltre di utilizzare sempre un sistema statico (condiviso in VB.NET ).Treading.Timer se si sta sviluppando un servizio di Windows e si richiede l'esecuzione periodica di un timer. Ciò eviterà l'eventuale raccolta prematura di oggetti timer.
Ecco un esempio di timer in un'applicazione 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
}
}
Dal libro CLR Via C # di Jeff Richter. A proposito, questo libro descrive la logica alla base dei 3 tipi di timer nel Capitolo 23, altamente raccomandato.
Ecco il codice per creare un semplice tick di un secondo:
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);
}
}
}
Ed ecco l'output risultante:
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: Non è mai una buona idea aggiungere loop di spin nel codice poiché consumano cicli CPU senza guadagno. In questo caso quel loop è stato aggiunto solo per impedire la chiusura dell'applicazione, consentendo di osservare le azioni del thread. Ma per motivi di correttezza e per ridurre l'utilizzo della CPU a quel loop è stata aggiunta una semplice chiamata Sleep.
Divertiamoci un po '
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(" DEFUSE 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();
}
}
}
O usando Rx, breve e dolce:
static void Main()
{
Observable.Interval(TimeSpan.FromSeconds(10)).Subscribe(t => Console.WriteLine("I am called... {0}", t));
for (; ; ) { }
}
Puoi anche usare i tuoi meccanismi di temporizzazione se vuoi un po 'più di controllo, ma forse meno precisione e più codice / complessità, ma consiglierei comunque un timer. Utilizzare questo però se è necessario avere il controllo sul thread di temporizzazione effettivo:
private void ThreadLoop(object callback)
{
while(true)
{
((Delegate) callback).DynamicInvoke(null);
Thread.Sleep(5000);
}
}
sarebbe il tuo thread di temporizzazione (modificalo per interrompere quando richiesto e in qualunque intervallo di tempo desideri).
e per usare / iniziare puoi fare:
Thread t = new Thread(new ParameterizedThreadStart(ThreadLoop));
t.Start((Action)CallBack);
La richiamata è il metodo vuoto senza parametri che si desidera chiamare ad ogni intervallo. Per esempio:
private void CallBack()
{
//Do Something.
}
Puoi anche crearne uno tuo (se insoddisfatto delle opzioni disponibili).
Creare la tua Timer
implementazione è roba piuttosto semplice.
Questo è un esempio per un'applicazione che necessitava dell'accesso all'oggetto COM sullo stesso thread del resto della mia base di codice.
/// <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();
}
}
È possibile aggiungere eventi come segue:
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);
Per assicurarsi che il timer funzioni è necessario creare un ciclo infinito come segue:
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();
}
}
Ecco qua :)
public static void Main()
{
SetTimer();
Console.WriteLine("\nPress the Enter key to exit the application...\n");
Console.WriteLine("The application started at {0:HH:mm:ss.fff}", DateTime.Now);
Console.ReadLine();
aTimer.Stop();
aTimer.Dispose();
Console.WriteLine("Terminating the application...");
}
private static void SetTimer()
{
// Create a timer with a two second interval.
aTimer = new System.Timers.Timer(2000);
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += OnTimedEvent;
aTimer.AutoReset = true;
aTimer.Enabled = true;
}
private static void OnTimedEvent(Object source, ElapsedEventArgs e)
{
Console.WriteLine("The Elapsed event was raised at {0:HH:mm:ss.fff}",
e.SignalTime);
}
Ti consiglio di seguire le linee guida Microsoft ( https://docs.microsoft.com/en-us/dotnet/api/system.timers.timer.interval?view=netcore-3.1 ).
Prima ho provato a usare System.Threading;
con
var myTimer = new Timer((e) =>
{
// Code
}, null, TimeSpan.Zero, TimeSpan.FromSeconds(5));
ma si è fermato continuamente dopo ~ 20 minuti.
Con ciò, ho provato l'impostazione delle soluzioni
GC.KeepAlive(myTimer)
o
for (; ; ) { }
}
ma non hanno funzionato nel mio caso.
A seguito della documentazione Microsoft, ha funzionato perfettamente:
using System;
using System.Timers;
public class Example
{
private static Timer aTimer;
public static void Main()
{
// Create a timer and set a two second interval.
aTimer = new System.Timers.Timer();
aTimer.Interval = 2000;
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += OnTimedEvent;
// Have the timer fire repeated events (true is the default)
aTimer.AutoReset = true;
// Start the timer
aTimer.Enabled = true;
Console.WriteLine("Press the Enter key to exit the program at any time... ");
Console.ReadLine();
}
private static void OnTimedEvent(Object source, System.Timers.ElapsedEventArgs e)
{
Console.WriteLine("The Elapsed event was raised at {0}", e.SignalTime);
}
}
// The example displays output like the following:
// Press the Enter key to exit the program at any time...
// The Elapsed event was raised at 5/20/2015 8:48:58 PM
// The Elapsed event was raised at 5/20/2015 8:49:00 PM
// The Elapsed event was raised at 5/20/2015 8:49:02 PM
// The Elapsed event was raised at 5/20/2015 8:49:04 PM
// The Elapsed event was raised at 5/20/2015 8:49:06 PM