(Post 23/11/2007) The easiest way to execute
a method periodically is using a timer – such as the Timer class provided
in the System.Threading namespace. The threading timer takes advantage
of the thread pool, allowing many timers to be created without the overhead
of many threads. Timer is a fairly simple class, with a constructor and
just two methods (a delight for minimalists, as well as book authors!)
public sealed class Timer :
MarshalByRefObject, IDisposable
{
public Timer (TimerCallback tick, object state, 1st, subsequent);
public bool Change (1st, subsequent); // To change the interval
public void Dispose(); // To kill the timer
}
1st = time to the first tick in milliseconds or a TimeSpan
subsequent = subsequent intervals in milliseconds or a TimeSpan
(use Timeout.Infinite for a one-off callback)
In the following example, a timer calls the Tick method which writes "tick..."
after 5 seconds have elapsed, then every second after that – until the
user presses Enter:
using System;
using System.Threading;
class Program {
static void Main() {
Timer tmr = new Timer (Tick, "tick...", 5000, 1000);
Console.ReadLine();
tmr.Dispose(); // End the timer
}
static void Tick (object data) {
// This runs on a pooled thread
Console.WriteLine (data); // Writes "tick..."
}
}
The .NET framework provides another timer class of the
same name in the System.Timers namespace. This simply wraps System.Threading.Timer,
providing additional convenience while using the same thread pool – and
the identical underlying engine. Here's a summary of its added features:
- A Component implementation, allowing it to be sited in the Visual
Studio Designer
- An Interval property instead of a Change method
- An Elapsed event instead of a callback delegate
- An Enabled property to start and pause the timer (its default value
being false)
- Start and Stop methods in case you're confused by Enabled
- an AutoReset flag for indicating a recurring event (default value
true)
Here's an example:
using System;
using System.Timers; // Timers namespace rather than Threading
class SystemTimer {
static void Main() {
Timer tmr = new Timer(); // Doesn't require any args
tmr.Interval = 500;
tmr.Elapsed += tmr_Elapsed; // Uses an event instead of a delegate
tmr.Start(); // Start the timer
Console.ReadLine();
tmr.Stop(); // Pause the timer
Console.ReadLine();
tmr.Start(); // Resume the timer
Console.ReadLine();
tmr.Dispose(); // Permanently stop the timer
}
static void tmr_Elapsed (object sender, EventArgs e) {
Console.WriteLine ("Tick");
}
}
The .NET framework provides yet a third timer – in the
System.Windows.Forms namespace. While similar to System.Timers.Timer in
its interface, it's radically different in the functional sense. A Windows
Forms timer does not use the thread pool, instead firing its "Tick"
event always on the same thread that originally created the timer. Assuming
this is the main thread – also responsible for instantiating all the forms
and controls in the Windows Forms application – the timer's event handler
is then able to interact with the forms and controls without violating
thread-safety – or the impositions of apartment-threading. Control.Invoke
is not required.
A Windows Forms timer is intended for jobs that may involve
updating the user interface and which execute quickly. Quick execution
is important because the Tick event is called on the main thread – which
if tied up, will make the user interface unresponsive.
(Sưu tầm) |