그냥-C # 콘솔 응용 프로그램에 타이머를 어떻게 추가합니까? 예제 코딩을 제공 할 수 있다면 좋을 것입니다.
그냥-C # 콘솔 응용 프로그램에 타이머를 어떻게 추가합니까? 예제 코딩을 제공 할 수 있다면 좋을 것입니다.
답변:
시간이 지남에 따라 시뮬레이션하려면 시간이 걸리는 명령을 실행해야하며 두 번째 예에서는 매우 분명합니다.
그러나 for 루프를 사용하여 일부 기능을 수행하는 스타일에는 많은 장치 리소스가 필요하지만 가비지 수집기를 사용하여 이와 같은 작업을 수행 할 수 있습니다.
동일한 책 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()
. 수집 할 것이 없습니다. GC.KeepAlive(t)
호출 된 경우 다음과 같이 의미 가 있습니다.Console.ReadLine();
System.Threading.Timer 클래스를 사용하십시오.
System.Windows.Forms.Timer는 주로 단일 스레드, 일반적으로 Windows Forms UI 스레드에서 사용하도록 설계되었습니다.
.NET 프레임 워크 개발 초기에 System.Timers 클래스가 추가되었습니다. 그러나 System.Threading.Timer 클래스는 System.Threading.Timer 주위의 래퍼이므로 일반적으로 대신 System.Threading.Timer 클래스를 사용하는 것이 좋습니다.
Windows 서비스를 개발 중이고 주기적으로 타이머를 실행해야하는 경우 항상 정적 (VB.NET에서 공유) System.Threading.Timer를 사용하는 것이 좋습니다. 이것은 타이머 객체의 조기 가비지 수집을 피할 것입니다.
다음은 콘솔 응용 프로그램의 타이머 예입니다.
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의 CLR Via C # 책에서 . 그런데이 책은 23 장의 3 가지 유형의 타이머에 대한 이론적 근거를 적극 권장합니다.
간단한 1 초 타이머 틱을 만드는 코드는 다음과 같습니다.
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);
}
}
}
결과는 다음과 같습니다.
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
편집 : 코드에 하드 스핀 루프를 추가하지 않고 CPU 사이클을 소비하므로 코드에 추가하는 것은 좋은 생각이 아닙니다. 이 경우 응용 프로그램이 닫히지 않도록 루프가 추가되어 스레드의 동작을 관찰 할 수 있습니다. 그러나 정확성을 위해 그리고 CPU 사용량을 줄이기 위해 간단한 Sleep 호출이 해당 루프에 추가되었습니다.
조금 재미있게 보내자
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();
}
}
}
또는 짧고 달콤한 Rx를 사용하십시오.
static void Main()
{
Observable.Interval(TimeSpan.FromSeconds(10)).Subscribe(t => Console.WriteLine("I am called... {0}", t));
for (; ; ) { }
}
약간의 제어를 원하지만 정확도와 코드 / 복잡성을 낮추려면 자체 타이밍 메커니즘을 사용할 수도 있지만 타이머를 권장합니다. 실제 타이밍 스레드를 제어해야하는 경우이를 사용하십시오.
private void ThreadLoop(object callback)
{
while(true)
{
((Delegate) callback).DynamicInvoke(null);
Thread.Sleep(5000);
}
}
타이밍 스레드가 될 것입니다 (요청 할 때, 원하는 시간 간격으로 중지하도록 수정하십시오).
사용 / 시작하려면 다음을 수행하십시오.
Thread t = new Thread(new ParameterizedThreadStart(ThreadLoop));
t.Start((Action)CallBack);
콜백은 매 간격마다 호출하려는 void 매개 변수가없는 메서드입니다. 예를 들면 다음과 같습니다.
private void CallBack()
{
//Do Something.
}
사용 가능한 옵션에 만족하지 않는 경우 직접 만들 수도 있습니다.
자신의 Timer
구현을 만드는 것은 매우 기본적인 것입니다.
이것은 내 코드베이스의 나머지 부분과 동일한 스레드에서 COM 개체 액세스가 필요한 응용 프로그램의 예입니다.
/// <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();
}
}
다음과 같이 이벤트를 추가 할 수 있습니다.
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);
타이머가 작동하도록하려면 다음과 같이 무한 루프를 만들어야합니다.
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();
}
}
거기 있습니다 :)
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 지침 ( https://docs.microsoft.com/en-us/dotnet/api/system.timers.timer.interval?view=netcore-3.1) 을 따르는 것이 좋습니다. ) .
나는 처음에 System.Threading;
함께 사용해 보았습니다.
var myTimer = new Timer((e) =>
{
// Code
}, null, TimeSpan.Zero, TimeSpan.FromSeconds(5));
~ 20 분 후에 계속 중지되었습니다.
그걸로 솔루션 설정을 시도했습니다.
GC.KeepAlive(myTimer)
또는
for (; ; ) { }
}
그러나 그들은 내 경우에는 효과가 없었습니다.
Microsoft 설명서에 따르면 완벽하게 작동했습니다.
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