Chỉ thế này - Làm thế nào để bạn thêm bộ hẹn giờ vào ứng dụng bảng điều khiển C #? Sẽ thật tuyệt nếu bạn có thể cung cấp một số ví dụ về mã hóa.
Chỉ thế này - Làm thế nào để bạn thêm bộ hẹn giờ vào ứng dụng bảng điều khiển C #? Sẽ thật tuyệt nếu bạn có thể cung cấp một số ví dụ về mã hóa.
Câu trả lời:
Điều đó rất hay, tuy nhiên để mô phỏng một thời gian trôi qua, chúng ta cần chạy một lệnh mất một thời gian và điều đó rất rõ ràng trong ví dụ thứ hai.
Tuy nhiên, phong cách sử dụng vòng lặp for để thực hiện một số chức năng mãi mãi tốn rất nhiều tài nguyên thiết bị và thay vào đó chúng ta có thể sử dụng Trình thu gom rác để làm một số việc như vậy.
Chúng ta có thể thấy sự sửa đổi này trong mã từ cùng một cuốn sách 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()
. Không có gì để thu thập. Nó sẽ có ý nghĩa, nếu GC.KeepAlive(t)
được gọi sauConsole.ReadLine();
Sử dụng lớp System.Threading.Timer.
System.Windows.Forms.Timer được thiết kế chủ yếu để sử dụng trong một luồng duy nhất thường là luồng UI của Windows Forms.
Ngoài ra còn có một lớp System.Timers được thêm vào sớm trong quá trình phát triển .NET framework. Tuy nhiên, thông thường nên sử dụng lớp System.Threading.Timer thay vì đây chỉ là một trình bao bọc xung quanh System.Threading.Timer.
Bạn cũng nên luôn luôn sử dụng Hệ thống tĩnh (được chia sẻ trong VB.NET) .Threading.Timer nếu bạn đang phát triển Dịch vụ Windows và yêu cầu bộ hẹn giờ để chạy định kỳ. Điều này sẽ tránh khả năng thu gom rác sớm của đối tượng hẹn giờ của bạn.
Đây là một ví dụ về bộ đếm thời gian trong ứng dụng giao diện điều khiển:
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
}
}
Từ cuốn sách CLR Via C # của Jeff Richter. Nhân tiện, cuốn sách này mô tả cơ sở lý luận đằng sau 3 loại bộ định thời trong Chương 23, rất được khuyến khích.
Đây là mã để tạo một dấu thời gian một giây đơn giản:
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);
}
}
}
Và đây là kết quả đầu ra:
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: Không bao giờ nên thêm các vòng lặp cứng vào mã khi chúng tiêu thụ chu kỳ CPU mà không thu được. Trong trường hợp này, vòng lặp đó đã được thêm vào chỉ để ngăn ứng dụng đóng lại, cho phép các hành động của luồng được quan sát. Nhưng vì mục đích chính xác và để giảm việc sử dụng CPU, một cuộc gọi Ngủ đơn giản đã được thêm vào vòng lặp đó.
Hãy vui vẻ một chút
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();
}
}
}
Hoặc sử dụng Rx, ngắn và ngọt ngào:
static void Main()
{
Observable.Interval(TimeSpan.FromSeconds(10)).Subscribe(t => Console.WriteLine("I am called... {0}", t));
for (; ; ) { }
}
Bạn cũng có thể sử dụng các cơ chế thời gian của riêng mình nếu bạn muốn kiểm soát nhiều hơn một chút, nhưng có thể kém chính xác hơn và nhiều mã / độ phức tạp hơn, nhưng tôi vẫn khuyên bạn nên sử dụng bộ hẹn giờ. Sử dụng điều này mặc dù nếu bạn cần kiểm soát luồng thời gian thực tế:
private void ThreadLoop(object callback)
{
while(true)
{
((Delegate) callback).DynamicInvoke(null);
Thread.Sleep(5000);
}
}
sẽ là chuỗi thời gian của bạn (sửa đổi điều này thành dừng khi được yêu cầu và tại bất kỳ khoảng thời gian nào bạn muốn).
và để sử dụng / bắt đầu, bạn có thể làm:
Thread t = new Thread(new ParameterizedThreadStart(ThreadLoop));
t.Start((Action)CallBack);
Gọi lại là phương thức không tham số void mà bạn muốn gọi ở mỗi khoảng thời gian. Ví dụ:
private void CallBack()
{
//Do Something.
}
Bạn cũng có thể tạo riêng của mình (nếu không hài lòng với các tùy chọn có sẵn).
Tạo Timer
thực hiện của riêng bạn là công cụ khá cơ bản.
Đây là một ví dụ cho một ứng dụng cần truy cập đối tượng COM trên cùng một luồng với phần còn lại của cơ sở mã của tôi.
/// <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();
}
}
Bạn có thể thêm các sự kiện như sau:
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);
Để đảm bảo bộ hẹn giờ hoạt động, bạn cần tạo một vòng lặp vô tận như sau:
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();
}
}
Có bạn có 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);
}
Tôi khuyên bạn nên làm theo hướng dẫn của Microsoft ( https://docs.microsoft.com/en-us/dotnet/api/system.timers.timer.interval?view=netcore-3.1 ).
Lần đầu tiên tôi thử sử dụng System.Threading;
với
var myTimer = new Timer((e) =>
{
// Code
}, null, TimeSpan.Zero, TimeSpan.FromSeconds(5));
nhưng nó liên tục dừng lại sau ~ 20 phút.
Với điều đó, tôi đã thử cài đặt giải pháp
GC.KeepAlive(myTimer)
hoặc là
for (; ; ) { }
}
nhưng họ đã không làm việc trong trường hợp của tôi.
Theo tài liệu của Microsoft, nó hoạt động hoàn hảo:
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