C#: cronometru corect cu Timer și Stopwatch
Construiește un cronometru C# care măsoară timpul scurs, fără să numere evenimente Tick. Separă măsurarea duratei de actualizarea interfeței grafice.
În acest material
Un Timer Windows Forms nu garantează că fiecare Tick apare exact la intervalul cerut. Dacă interfața este ocupată, evenimentul poate întârzia. Pentru un quiz cu limită de timp, numărarea tickurilor ar produce o durată incorectă. Stopwatch măsoară timpul scurs; Timer doar cere reîmprospătarea afișării.
Cum lucrezi cu exemplul
Exemplul complet se compilează ca Windows Forms App pe .NET Framework 4.8, cu C# 7.3. Deschide Lesson.csproj din arhivă în Visual Studio pe Windows. Rulează scenariile descrise mai jos; verificarea compilării nu înlocuiește testarea ferestrei și a dispozitivelor folosite.
Descarcă sursele și instrucțiunile.
Ideea și pașii de implementare
Exemplul pornește o probă de zece secunde. La fiecare Tick calculăm diferența dintre durata totală și Elapsed.TotalSeconds. Math.Ceiling oferă numărul de secunde întregi rămase pentru afișare, iar Math.Max previne valori negative. Când durata a fost depășită, oprim timerul și marcăm finalizarea.
Butonul Start folosește Restart, care resetează măsurarea. Dacă ai dori pauză și reluare, ai folosi Stop și Start în loc de Restart. Timerul este o resursă deținută de formular și trebuie oprit și eliberat când acesta se închide.
Exemplu și rezultat așteptat
La pornire vezi 10, apoi numărătoarea descrește către zero. După final apare Timp expirat și butonul poate iniția o probă nouă. Dacă un Tick întârzie, următoarea afișare sare la valoarea calculată din timpul real, fără să prelungească artificial proba.
Stopwatch: 0 → 10 s → Timer: actualizare periodică → Rămas = 10 − elapsed → La limită: închide proba.Mărește schema ↗
Codul complet
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Windows.Forms;
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new LessonForm());
}
}
class LessonForm : Form
{
readonly System.Windows.Forms.Timer timer=new System.Windows.Forms.Timer {Interval=100};
readonly System.Diagnostics.Stopwatch watch=new System.Diagnostics.Stopwatch();
readonly Label output=new Label {Left=20,Top=70,Width=300,Text="Apasa Start"};
public LessonForm() {
Text="Cronometru"; ClientSize=new Size(360,150);
var start=new Button {Left=20,Top=20,Text="Start"};
start.Click += (s,e) => {watch.Restart();timer.Start();RefreshTime();};
timer.Tick += (s,e) => RefreshTime(); Controls.AddRange(new Control[] {start,output});
}
void RefreshTime() {
double remaining=10-watch.Elapsed.TotalSeconds;
if(remaining<=0) {timer.Stop();watch.Stop();output.Text="Timp expirat";}
else output.Text="Ramase: " + Math.Ceiling(remaining) + " secunde";
}
protected override void Dispose(bool disposing) {
if(disposing) {timer.Stop();timer.Dispose();watch.Stop();} base.Dispose(disposing);
}
}
Greșeli și limite
Nu folosi Thread.Sleep pe firul interfeței pentru numărătoare: vei bloca desenarea și clickurile. Nu scădea pur și simplu unu la fiecare Tick. Nu crea un timer nou la fiecare apăsare fără să îl oprești pe cel precedent. Pentru scor, verifică expirarea și în operația de răspuns, nu numai în afișarea cronometrului.
Exersează
Schimbă durata la trei secunde și verifică pornirea repetată. Adaugă un buton Răspunde care acceptă acțiunea numai dacă Stopwatch.Elapsed este sub limită. Apasă în apropierea expirării și verifică faptul că regula folosește timpul măsurat, chiar dacă labelul nu a fost încă redesenat.
Continuă parcursul
Parcursul complet de 50 de lecții
Lecția precedentă: C#: comenzi de tastatură și focalizare previzibilă
Lecția următoare: C#: operații în fundal și anulare fără blocarea ferestrei.
Referință: documentația Microsoft.
Întrebări frecvente
Timer măsoară timpul exact?
Nu. În acest model el programează actualizarea interfeței; Stopwatch măsoară durata.
De ce nu folosesc Sleep?
Pe firul UI blochează evenimentele și face fereastra neutilizabilă.
Unde verific expirarea unui răspuns?
În regula care acceptă răspunsul, folosind timpul măsurat, nu doar textul afișat.
Un pas mai departe
Autentifică-te pentru a păstra progresul în cont.