2011-11-01 146 views
10

Tôi đang cố gắng để thực hiện một đếm ngược sử dụng C# và hiển thị thời gian ở định dạng:C# đồng hồ đếm ngược

hour:minutes:seconds 

Tôi đã thử điều này:

var minutes = 3; //countdown time 
    var start = DateTime.Now; 
    var end = DateTime.Now.AddMinutes(minutes); 
    Thread.Sleep(1800); 
    if (??) // I tried DateTime.Now > end not works 
    { 
     //... show time 
     label1.Text = "..."; 
    } 
    else 
    { 
    //done 
     label1.Text = "Done!"; 
    } 

Những cách khác nhau để giải quyết vấn đề này cũng xuất hiện. Cảm ơn trước

+0

Nếu bạn muốn cập nhật định kỳ nhãn, bạn sẽ cần thứ gì đó giống như vòng lặp. – svick

+2

@javasocute Tôi đã làm, tôi có những nghi ngờ về sự tỉnh táo của anh ấy. Đây là Winforms, và .net có các cơ chế hoàn hảo để xử lý những thứ như vậy. Không cần phải mang theo javascript cho một điều nhỏ như vậy. – CodesInChaos

Trả lời

28

Bạn không nên sử dụng Thread.Sleep tại đây. Thread.Sleep trên chuỗi giao diện người dùng chặn giao diện người dùng và sử dụng nó trên một chuỗi khác dẫn đến sự phức tạp bổ sung do đồng bộ hóa luồng.

Nếu bạn có C# 5 hoặc CTP không đồng bộ, bạn có thể viết mã rất giống với những gì bạn đã làm, vì sau đó bạn nhận được số tương đương dựa trên số Thread.Sleep không chặn giao diện người dùng.

Trong tiêu chuẩn C# 4, tôi muốn sử dụng số System.Windows.Forms.Timer.

Để bắt đầu đếm ngược:

var minutes = 3; //countdown time 
var start = DateTime.UtcNow; // Use UtcNow instead of Now 
endTime = start.AddMinutes(minutes); //endTime is a member, not a local variable 
timer1.Enabled = true; 

Trong xử lý timer bạn viết:

TimeSpan remainingTime=endTime-DateTime.UtcNow; 
if(remainingTime<TimeSpan.Zero) 
{ 
    label1.Text = "Done!"; 
    timer1.Enabled=false; 
} 
else 
{ 
    label1.Text = remainingTime.ToString(); 
} 

Đối với tùy chọn định dạng khác nhìn thấy Standard TimeSpan Format Strings.

Một vấn đề tồn tại với mã này là nó sẽ không hoạt động chính xác nếu đồng hồ hệ thống thay đổi.

Khi sử dụng DateTime.Now thay vì DateTime.UtcNow nó cũng sẽ bị ngắt khi chuyển từ/sang chế độ tiết kiệm ánh sáng ban ngày hoặc thay đổi múi giờ. Vì bạn muốn xác định một điểm nhất định trong thời gian (và không phải là thời gian hiển thị), bạn nên sử dụng UTC thay vì giờ địa phương.

+0

Cảm ơn rất nhiều! 1 cho câu trả lời tốt, nhưng tôi có một vấn đề trong statament: 'Lỗi: Operator '<' không thể được áp dụng cho các toán hạng của loại 'System.TimeSpan' và 'int'' làm thế nào tôi sửa chữa nó? –

+0

@TheMask Sử dụng 'TimeSpan.Zero' thay vì' 0' – CodesInChaos

+1

CodeInChaos: Người đó thực sự làm việc. Hoạt động hoàn hảo. Cảm ơn rất nhiều. :) –

0

Mã của bạn thiết lập các biến sau đó chuyển sang chế độ ngủ trong 3 phút để câu lệnh if không được thực thi cho đến khi nó thoát khỏi trạng thái ngủ. Hoặc thiết lập một chủ đề mới để cập nhật giao diện người dùng hoặc làm điều gì đó như thế này ...

while (DateTime.now < end) { 
    label1.Text = "..."; 
    Thread.Sleep(#); //Pick a second, or 5 or whatever 
} 

label1.Text = "Done!"; 

Với chủ đề thứ 2 bạn vẫn có thể làm công cụ trong chương trình của bạn trong khi nó hoạt động. "Làm xong!" sẽ xuất hiện khi nó kết thúc.

+1

Sử dụng bộ hẹn giờ, không phải 'Thread.Sleep()'. Sử dụng giấc ngủ là một sự lãng phí của một sợi chỉ. –

+0

Cảm ơn tuyệt vời, tôi không phải là một anh chàng C# trong trái tim và chỉ là xây dựng ra khỏi mã của mình. – Grambot

+0

Họ có bộ hẹn giờ trong Java :) –

5

Tôi sẽ sử dụng bộ hẹn giờ như thế này. Đầu tiên là một vài biến mẫu.

private int _countDown = 30; // Seconds 
private Timer _timer; 

và trong các nhà xây dựng hoặc tải sự kiện

_timer = new Timer(); 
_timer.Tick += new EventHandler(timer_Tick); 
_timer.Interval = 1000; 
_timer.Start(); 

và sau đó cuối cùng là xử lý sự kiện

void timer_Tick(object sender, EventArgs e) 
{ 
    _countDown--; 
    if (_countDown < 1) 
    { 
     _countDown = 30; 
    } 
    lblCountDown.Text = _countDown.ToString(); 
} 
1

Bạn cũng có thể sử dụng một hẹn giờ, vì điều này sẽ xử lý tất cả những vấn đề giống như khóa giao diện người dùng. Bạn có thể sử dụng System.Windows.Forms.Timer -Timer. Trong thư viện MSDN bạn có thể tìm thấy các mẫu của việc sử dụng nó.

Bộ đếm thời gian WinForms cũng xử lý cuộc gọi trên chuỗi bộ đếm thời gian và chuỗi giao diện người dùng.

- SeriTools

Các vấn đề liên quan