2009-06-02 1 views
7

저는 C#으로 간단한 카운트 다운 - 응용 프로그램을 만들고 싶었습니다.C# 간단한 카운트 다운 - 내가 뭘 잘못하고 있니?

첫 번째 및 기본 버전의 경우 현재 시간을 초로 표시하는 Label과 카운트 다운을 시작하는 Button을 사용합니다. 버튼의 클릭 이벤트는 다음과 같이 구현 : 사용자가 시간의 선택 금액 만 (때문에 수면())에 (응용 프로그램이 정지 등) 시간이 실제로 카운트 다운 버튼을 클릭 지금

private void ButtonStart_Click(object sender, RoutedEventArgs e) 
    { 
     _time = 60; 
     while (_time > 0) 
     { 
      _time--; 
      this.labelTime.Content = _time + "s"; 
      System.Threading.Thread.Sleep(1000); 
     } 
    } 

레이블의 컨텍스트가 새로 고쳐지지 않습니다.

내가 일반적으로 잘못하고있는 것은 (스레드와 관련하여) 또는 UI에 문제가 있습니까?


답장을 보내 주셔서 감사합니다. 이제 System.Windows.Threading.DispatcherTimer를 사용하여 나에게 말한대로 할 수 있습니다. 모든 그래서이 질문은 공식적으로 대한 답변 잘 작동) 관심이있는 사람들을 위해

: 여기 내 코드 (핵심 부품)

public partial class WindowCountdown : Window 
{ 
    private int _time; 
    private DispatcherTimer _countdownTimer; 

    public WindowCountdown() 
    { 
     InitializeComponent(); 
     _countdownTimer = new DispatcherTimer(); 
     _countdownTimer.Interval = new TimeSpan(0,0,1); 
     _countdownTimer.Tick += new EventHandler(CountdownTimerStep); 

    } 

    private void ButtonStart_Click(object sender, RoutedEventArgs e) 
    { 
     _time = 10; 
     _countdownTimer.Start(); 

    } 

    private void CountdownTimerStep(object sender, EventArgs e) 
    { 
     if (_time > 0) 
     { 
      _time--; 
      this.labelTime.Content = _time + "s"; 
     } 
     else 
      _countdownTimer.Stop(); 
    } 
} 

답변

10

예, 이벤트 핸들러 차단 안입니다 - 그들은 즉시 반환해야합니다가. Timer, BackgroundWorker 또는 Thread (이 순서대로)로 구현해야합니다.

9

당신이보고있는 것은 창 메시지 대기열/펌프를 차단하는 장기 실행 메시지의 효과입니다.이 메시지는 일반적으로 흰색 애플리케이션 화면과 관련이 있으며 "응답하지 않음"입니다. 기본적으로 스레드가 잠자고 있다면 "페인트하기"와 같은 메시지에 응답하지 않습니다. 변경해야하며 항복 조절 장치을 펌프에 연결해야합니다.

이렇게하는 방법에는 여러 가지가 있습니다 (ripper234는 좋은 방법입니다). 자주 보게되는 나쁜 방법은 다음과 같습니다

{ // your count/sleep loop 

    // bad code - don't do this: 
    Application.DoEvents(); 
    System.Threading.Thread.Sleep(1000); 
} 

내가 하지이 무엇을 강조하기 위해이 을 언급; 이것은 "re-entrancy"와 일반적인 코드 관리에 많은 문제를 야기합니다. 더 좋은 방법은 단순히 Timer을 사용하거나 더 복잡한 코드 인 BackgroundWorker을 사용하는 것입니다. 다음과 같음 :

using System; 
using System.Windows.Forms; 
class MyForm : Form { 
    [STAThread] 
    static void Main() { 
     Application.EnableVisualStyles(); 
     Application.Run(new MyForm()); 
    } 

    Timer timer; 
    MyForm() { 
     timer = new Timer(); 
     count = 10; 
     timer.Interval = 1000; 
     timer.Tick += timer_Tick; 
     timer.Start(); 
    } 
    protected override void Dispose(bool disposing) { 
     if (disposing) { 
      timer.Dispose(); 
     } 
     base.Dispose(disposing); 
    } 
    int count; 
    void timer_Tick(object sender, EventArgs e) { 
     Text = "Wait for " + count + " seconds..."; 
     count--; 
     if (count == 0) 
     { 
      timer.Stop(); 
     } 
    } 
} 
관련 문제