2010-09-18 14 views
10

इंटरफ़ेस को अद्यतन करने के तरीके पर जटिलताओं के कारण WPF में मुझे कभी-कभी छोटी देरी के बाद कार्रवाई करना पड़ता है।विलंबित प्रेषण का आह्वान?

वर्तमान में मैं बस द्वारा इस कर रहा हूँ: (?)

 var dt = new DispatcherTimer(DispatcherPriority.Send); 
     dt.Tick += (s, e) => 
     { 
      dt.Stop(); 
      //DoStuff 
     }; 
     dt.Interval = TimeSpan.FromMilliseconds(200); 
     dt.Start(); 

लेकिन यह हर बार एक नई घड़ी बनाने के लिए दोनों एक सा बदसूरत और शायद बहुत ज्यादा भूमि के ऊपर है क्या करने के लिए एक प्रदर्शन के दृष्टिकोण से सबसे अच्छा है ऐसा करो, यानी सबसे तुरंत निष्पादित करें?

 this.Dispatcher.BeginInvoke(new Action(delegate() 
     { 
      //DoStuff 
     }), DispatcherPriority.Send,TimeSpan.FromMilliseconds(200)); 

कहाँ समयावधि देरी है, किसी भी इनपुट :)

+0

, आप जिम्मेदारी नहीं ले जा सकते हैं:

public static class DispatcherExtensions { public static void Delay(this Dispatcher disp, int delayMs, Action<object> action, object parm = null) { var ignore = Task.Delay(delayMs).ContinueWith((t) => { disp.Invoke(action, parm); }); } public static void DelayWithPriority(this Dispatcher disp, int delayMs, Action<object> action, object parm = null, DispatcherPriority priority = DispatcherPriority.ApplicationIdle) { var ignore = Task.Delay(delayMs).ContinueWith((t) => { disp.BeginInvoke(action, priority, parm); }); } public static async Task DelayAsync(this Dispatcher disp, int delayMs, Action<object> action, object parm = null, DispatcherPriority priority = DispatcherPriority.ApplicationIdle) { await Task.Delay(delayMs); await disp.BeginInvoke(action, priority, parm); } } 

तो यह कॉल करने के लिए जिस यूआई पर आप इंतजार कर रहे हैं उस यूआई को अपडेट करने के लिए? यह टाइमर से बच जाएगा।दुर्भाग्यवश – x0n

+0

दुर्भाग्य से नहीं, यह हैई को अपडेट करने और इसे थोड़ी देर के बाद छिपाने जैसी हैकी चीजें हैं, इसलिए विंडो को अपडेट किया जाता है जब इसे फिर से दिखाया जाता है – Homde

उत्तर

11

के लिए धन्यवाद मुझे लगता है नहीं हैं कि DispatcherTimer भारी वजन है: और की तरह कुछ में इसके बाद के संस्करण कोड के पुनर्लेखन के लिए अच्छा तरीका है ... क्यों न केवल पर एक विस्तार विधि लिखें जो आपको इच्छित वाक्यविन्यास का उपयोग करने की अनुमति देता है, और पृष्ठभूमि में DispatcherTimer का उपयोग करता है? मैं व्यक्तिगत रूप से हालांकि बल्कि BeginInvoke से DelayInvoke यह कहेंगे ... और मैं भी इसे ठीक था हमेशा एक मनमाना प्रतिनिधि ... कि यह आसान लैम्ब्डा एक्सप्रेशन का उपयोग करने देगा बजाय Action उपयोग करने के लिए:

Dispatcher.DelayInvoke(TimeSpan.FromMilliseconds(200),() => { ... 
}); 

(अगर मुझे किसी विधि कॉल में अंतिम तर्क के रूप में अज्ञात फ़ंक्शंस का उपयोग किया जाता है, तो मुझे यह और अधिक पठनीय लगता है, लेकिन यह केवल एक व्यक्तिगत वरीयता है।)

यह देखते हुए कि आप संभवतः अधिकांश समय मिलीसेकंड का उपयोग करना चाहते हैं, आप एक और सहायक विधि भी हो सकती है:

Dispatcher.DelayInvokeMillis(200,() => { ... 
}); 

प्रयास करने का एक और विकल्प केवल मौजूदा BeginInvoke विधि का उपयोग करना है, लेकिन बहुत कम प्राथमिकता के साथ, इसलिए आपके प्रतिनिधि को केवल बाकी सब कुछ खत्म होने के बाद ही बुलाया जाएगा। अपनी स्थिति के ब्योरे को जानने के बिना, यह जानना मुश्किल है कि वह काम करेगा या नहीं - लेकिन यह कोशिश करने लायक है।

+0

एक एक्सटेंशन विधि बहुत अच्छी होगी, लेकिन इसका मतलब यह नहीं होगा कि मुझे पहले स्टार्टिनवोक करना होगा प्रेषक पर दाहिने धागे पर होना और फिर टाइमर सेट करना, जो टाइमर होने से थोड़ा अधिक ओवरहेड है? हालांकि कोई मुद्दा नहीं हो सकता है ... – Homde

+0

@MattiasK: ऐसा करने की आवश्यकता क्यों होगी? यह * वास्तव में * प्रेषक के साथ बातचीत करने की ज़रूरत नहीं होगी ... यह केवल स्थिरता की भावना के लिए होगा। माना जाता है कि मुझे नहीं पता कि क्या होता है यदि आप एक अलग थ्रेड से डिस्पैचर टिमर बनाते हैं ... लेकिन यदि यह सीधे किया जाता है तो यह काम करता है, तो यह किसी अतिरिक्त समस्या के बिना एक्सटेंशन विधि से काम करेगा। –

+2

@ मैटियासके: मैंने अभी जांच की है, और आप डिस्पैचर टिमर कन्स्ट्रक्टर को बता सकते हैं कि डिस्पैचर इसे चालू करना चाहिए - ताकि आप एक्सटेंशन विधि से उस अधिभार का उपयोग कर सकें और विधि को पास किए गए डिस्पैचर को निर्दिष्ट कर सकें। –

0

आप पॉल स्टोवेल की देरी बाइंडिंग कक्षा का उपयोग यहां से कर सकते हैं: http://www.paulstovell.com/wpf-delaybinding

इसके साथ एक वर्ग पर निर्भरता प्रॉपर्टी से जुड़ सकता है जो संपत्ति में परिवर्तन के दौरान कार्रवाई निष्पादित कर सकता है। बाध्यकारी देरी का प्रबंधन करेगा। यदि आपके पास एमवीवीएम-प्रकार का डिज़ाइन है तो विशेष रूप से अच्छा हो सकता है।

3

एक .NET 4.5 रास्ता:

public async void MyMethod() 
    { 
     await Task.Delay(20); 
     await Dispatcher.BeginInvoke((Action)DoStuff); 
    } 
0

मैं DispatcherTimer के शौकीन नहीं हूँ समारोह गुंजाइश/बंद के माध्यम से के अलावा अन्य में पैरामीटर पास कोई आसान तरीका है क्योंकि वहाँ।

इसके बजाय मैं एक Task.Delay() का उपयोग करें और लपेट कि एक Dispatcher.Delay() विस्तार विधि में: इसके बजाय अद्यतन करने से पहले कुछ के लिए इंतजार की

Dispatcher.Delay(4000, (win) => 
{ 
    var window = win as MainWindow; 
    window.ShowStatus(null, 0); 
},this); 
संबंधित मुद्दे