Genau das - Wie fügt man einer C # -Konsolenanwendung einen Timer hinzu? Es wäre großartig, wenn Sie eine Beispielcodierung liefern könnten.
Genau das - Wie fügt man einer C # -Konsolenanwendung einen Timer hinzu? Es wäre großartig, wenn Sie eine Beispielcodierung liefern könnten.
Antworten:
Das ist sehr schön, aber um einige Zeit zu simulieren, müssen wir einen Befehl ausführen, der einige Zeit in Anspruch nimmt, und das ist im zweiten Beispiel sehr klar.
Der Stil, eine for-Schleife zu verwenden, um einige Funktionen für immer auszuführen, erfordert jedoch viele Geräteressourcen. Stattdessen können wir den Garbage Collector verwenden, um so etwas zu tun.
Wir können diese Änderung im Code aus demselben Buch CLR Via C # Third Ed sehen.
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()
. Es gibt nichts zu sammeln. Es wäre sinnvoll, wenn GC.KeepAlive(t)
nachConsole.ReadLine();
Verwenden Sie die System.Threading.Timer-Klasse.
System.Windows.Forms.Timer wurde hauptsächlich für die Verwendung in einem einzelnen Thread entwickelt, normalerweise dem Windows Forms-UI-Thread.
Es gibt auch eine System.Timers-Klasse, die zu Beginn der Entwicklung des .NET-Frameworks hinzugefügt wurde. Es wird jedoch generell empfohlen, stattdessen die System.Threading.Timer-Klasse zu verwenden, da dies ohnehin nur ein Wrapper um System.Threading.Timer ist.
Es wird außerdem empfohlen, immer ein statisches (in VB.NET freigegebenes) System.Threading.Timer zu verwenden, wenn Sie einen Windows-Dienst entwickeln und einen Timer benötigen, der regelmäßig ausgeführt wird. Dadurch wird möglicherweise eine vorzeitige Speicherbereinigung Ihres Timer-Objekts vermieden.
Hier ist ein Beispiel für einen Timer in einer Konsolenanwendung:
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
}
}
Aus dem Buch CLR Via C # von Jeff Richter. Übrigens beschreibt dieses Buch die Gründe für die drei Arten von Timern in Kapitel 23, die sehr zu empfehlen sind.
Hier ist der Code zum Erstellen eines einfachen Timer-Ticks von einer Sekunde:
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);
}
}
}
Und hier ist die resultierende Ausgabe:
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
BEARBEITEN: Es ist niemals eine gute Idee, Hard-Spin-Schleifen in den Code einzufügen, da diese CPU-Zyklen ohne Gewinn verbrauchen. In diesem Fall wurde diese Schleife hinzugefügt, um das Schließen der Anwendung zu verhindern und die Aktionen des Threads zu beobachten. Aus Gründen der Korrektheit und zur Reduzierung der CPU-Auslastung wurde dieser Schleife ein einfacher Sleep-Aufruf hinzugefügt.
Lass uns ein bisschen Spaß haben
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();
}
}
}
Oder mit Rx, kurz und bündig:
static void Main()
{
Observable.Interval(TimeSpan.FromSeconds(10)).Subscribe(t => Console.WriteLine("I am called... {0}", t));
for (; ; ) { }
}
Sie können auch Ihre eigenen Timing-Mechanismen verwenden, wenn Sie etwas mehr Kontrolle, aber möglicherweise weniger Genauigkeit und mehr Code / Komplexität wünschen, aber ich würde trotzdem einen Timer empfehlen. Verwenden Sie dies jedoch, wenn Sie die Kontrolle über den tatsächlichen Timing-Thread haben müssen:
private void ThreadLoop(object callback)
{
while(true)
{
((Delegate) callback).DynamicInvoke(null);
Thread.Sleep(5000);
}
}
Dies wäre Ihr Timing-Thread (ändern Sie dies so, dass es bei Bedarf und in jedem gewünschten Zeitintervall stoppt).
und um / start zu verwenden, können Sie tun:
Thread t = new Thread(new ParameterizedThreadStart(ThreadLoop));
t.Start((Action)CallBack);
Callback ist Ihre void parameterlose Methode, die Sie in jedem Intervall aufrufen möchten. Beispielsweise:
private void CallBack()
{
//Do Something.
}
Sie können auch Ihre eigenen erstellen (wenn Sie mit den verfügbaren Optionen nicht zufrieden sind).
Das Erstellen einer eigenen Timer
Implementierung ist ziemlich einfach.
Dies ist ein Beispiel für eine Anwendung, die Zugriff auf COM-Objekte im selben Thread wie der Rest meiner Codebasis benötigt.
/// <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();
}
}
Sie können Ereignisse wie folgt hinzufügen:
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);
Um sicherzustellen, dass der Timer funktioniert, müssen Sie eine Endlosschleife wie folgt erstellen:
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();
}
}
Hier hast du es :)
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);
}
Ich empfehle Ihnen, die Microsoft-Richtlinien zu befolgen ( https://docs.microsoft.com/en-us/dotnet/api/system.timers.timer.interval?view=netcore-3.1 ).
Ich versuchte zunächst mit System.Threading;
mit
var myTimer = new Timer((e) =>
{
// Code
}, null, TimeSpan.Zero, TimeSpan.FromSeconds(5));
aber es hörte kontinuierlich nach ~ 20 Minuten auf.
Damit habe ich die Lösungseinstellung ausprobiert
GC.KeepAlive(myTimer)
oder
for (; ; ) { }
}
aber in meinem Fall haben sie nicht funktioniert.
Nach der Microsoft-Dokumentation hat es perfekt funktioniert:
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