Sadece bu - Bir C # konsol uygulamasına nasıl zamanlayıcı eklersiniz? Örnek bir kodlama sunabilirseniz harika olur.
Sadece bu - Bir C # konsol uygulamasına nasıl zamanlayıcı eklersiniz? Örnek bir kodlama sunabilirseniz harika olur.
Yanıtlar:
Bu çok güzel, ancak geçen zamanı simüle etmek için biraz zaman alan bir komut çalıştırmamız gerekiyor ve bu ikinci örnekte çok açık.
Bununla birlikte, bazı işlevleri sonsuza kadar yapmak için bir for döngüsü kullanma stili çok fazla cihaz kaynağı gerektirir ve bunun yerine bunun gibi bir şey yapmak için Çöp Toplayıcıyı kullanabiliriz.
Bu değişikliği aynı CLR Via C # Third Ed kitabındaki kodda görebiliriz.
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()
. Toplanacak hiçbir şey yok. Daha GC.KeepAlive(t)
sonra Console.ReadLine();
System.Threading.Timer sınıfını kullanın.
System.Windows.Forms.Timer, öncelikle tek bir iş parçacığında, genellikle Windows Forms UI iş parçacığında kullanılmak üzere tasarlanmıştır.
Ayrıca .NET çerçevesinin geliştirilmesinin başlarında eklenen bir System.Timers sınıfı da vardır. Bununla birlikte, genellikle System.Threading.Timer sınıfının kullanılması önerilir çünkü bu, yine de System.Threading.Timer etrafında bir sarmalayıcıdır.
Ayrıca, bir Windows Hizmeti geliştiriyorsanız ve periyodik olarak çalışmak için bir zamanlayıcı gerekiyorsa, her zaman statik (VB.NET'te paylaşılan) bir System.Threading.Timer kullanmanız önerilir. Bu, zamanlayıcı nesnenizin olası erken çöp toplamasını önleyecektir.
Aşağıda, bir konsol uygulamasındaki bir zamanlayıcı örneği verilmiştir:
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
}
}
Jeff Richter'in CLR Via C # kitabından . Bu arada, bu kitap Bölüm 23'teki 3 tür zamanlayıcının arkasındaki mantığı açıklamaktadır, şiddetle tavsiye edilmektedir.
İşte bir saniyelik basit bir zamanlayıcı tik oluşturmak için kod:
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);
}
}
}
Ve işte ortaya çıkan çıktı:
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
DÜZENLEME: Kazanım olmadan CPU döngülerini tükettiklerinden koda sert döndürme döngüleri eklemek asla iyi bir fikir değildir. Bu durumda, döngü sadece uygulamanın kapanmasını durdurmak için eklendi ve iş parçacığının eylemlerinin gözlemlenmesine izin verildi. Ancak doğruluk ve CPU kullanımını azaltmak için bu döngüye basit bir Uyku çağrısı eklendi.
Biraz Eğlenelim
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();
}
}
}
Veya Rx kullanarak, kısa ve tatlı:
static void Main()
{
Observable.Interval(TimeSpan.FromSeconds(10)).Subscribe(t => Console.WriteLine("I am called... {0}", t));
for (; ; ) { }
}
Biraz daha fazla kontrol, ancak muhtemelen daha az doğruluk ve daha fazla kod / karmaşıklık istiyorsanız, kendi zamanlama mekanizmalarınızı da kullanabilirsiniz, ancak yine de bir zamanlayıcı tavsiye ederim. Gerçek zamanlama iş parçacığı üzerinde kontrol sahibi olmanız gerekiyorsa bunu kullanın:
private void ThreadLoop(object callback)
{
while(true)
{
((Delegate) callback).DynamicInvoke(null);
Thread.Sleep(5000);
}
}
zamanlama iş parçacığınız olabilir (bunu, gerektiğinde ve istediğiniz zaman aralığında duracak şekilde değiştirin).
ve kullanmak / başlatmak için şunları yapabilirsiniz:
Thread t = new Thread(new ParameterizedThreadStart(ThreadLoop));
t.Start((Action)CallBack);
Geri arama, her aralıkta çağrılmasını istediğiniz void parametresiz yönteminizdir. Örneğin:
private void CallBack()
{
//Do Something.
}
Ayrıca kendinizinkini de oluşturabilirsiniz (mevcut seçeneklerden memnun değilseniz).
Kendi Timer
uygulamanızı oluşturmak oldukça basit şeylerdir.
Bu, kod tabanımın geri kalanıyla aynı iş parçacığı üzerinde COM nesne erişimine ihtiyaç duyan bir uygulama örneğidir.
/// <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();
}
}
Olayları aşağıdaki şekilde ekleyebilirsiniz:
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);
Zamanlayıcının çalıştığından emin olmak için aşağıdaki gibi sonsuz bir döngü oluşturmanız gerekir:
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();
}
}
İşte aldın :)
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);
}
Microsoft yönergelerini ( https://docs.microsoft.com/en-us/dotnet/api/system.timers.timer.interval?view=netcore-3.1 ) izlemenizi öneririm .
İlk kullanarak çalıştı System.Threading;
ile
var myTimer = new Timer((e) =>
{
// Code
}, null, TimeSpan.Zero, TimeSpan.FromSeconds(5));
ancak ~ 20 dakika sonra sürekli olarak durdu.
Bununla çözüm ayarını denedim
GC.KeepAlive(myTimer)
veya
for (; ; ) { }
}
ama benim durumumda işe yaramadı.
Microsoft belgelerini takiben mükemmel çalıştı:
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