2009-06-02 14 views
7

मैं एक उदाहरण के रूप में दिखाने के लिए सी # के साथ एक सरल उलटी गिनती-आवेदन करना चाहता था।सी # सरल उलटी गिनती - मैं क्या गलत कर रहा हूँ?

पहले और मूल संस्करण के लिए मैं एक लेबल का उपयोग करता हूं ताकि वर्तमान समय सेकंड में छोड़ा जा सके और उलटी गिनती शुरू करने के लिए एक बटन प्रदर्शित किया जा सके। बटन के क्लिक-घटना इस तरह कार्यान्वित किया जाता है:

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

अब जब उपयोगकर्ता ((नींद()) के कारण आवेदन फ्रीज़ के रूप में) समय के चुने हुए राशि के लिए लेकिन बटन समय वास्तव में नीचे में गिना जाता है पर क्लिक करता है लेबल का संदर्भ ताज़ा नहीं किया जाता है।

क्या मैं कुछ सामान्य रूप से गलत कर रहा हूं (जब यह थ्रेड की बात आती है) या क्या यह यूआई के साथ एक समस्या है?


आपके उत्तरों के लिए धन्यवाद! अब मैं एक सिस्टम का उपयोग करता हूं। 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

हाँ, ईवेंट हैंडलर्स ब्लॉक नहीं चाहिए - वे तुरंत वापस आ जाएगी। आपको इसे टाइमर, पृष्ठभूमिवर्कर या थ्रेड (वरीयता के इस क्रम में) द्वारा कार्यान्वित करना चाहिए।

9

जो आप देख रहे हैं वह विंडोज संदेश कतार/पंप को अवरुद्ध करने वाले लंबे समय तक चलने वाले संदेश का प्रभाव है - जिसे आप आमतौर पर सफेद एप्लिकेशन स्क्रीन और "प्रतिक्रिया नहीं दे रहे" से जोड़ते हैं। असल में, यदि आपका धागा सो रहा है, तो यह "खुद को पेंट" जैसे संदेशों का जवाब नहीं दे रहा है। पंप में आपको अपना परिवर्तन और उपज नियंत्रण बनाना होगा।

ऐसा करने के कई तरीके हैं (ripper234 उन्हें सूचीबद्ध करने का अच्छा काम करता है)। बुरा तरीका अक्सर देखेंगे:

{ // your count/sleep loop 

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

मैं इस केवल उल्लेख नहीं क्या करना है उजागर करने के लिए; इससे "पुनः प्रवेश" और सामान्य कोड प्रबंधन के साथ कई समस्याएं होती हैं। 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(); 
     } 
    } 
} 
संबंधित मुद्दे