2013-05-31 21 views
6

मैं अपने विंडोज फोन 8 एमवीवीएम प्रोजेक्ट पर async/await का उपयोग करना चाहता हूं और मैं इस आईपीआई का उपयोग करके अपने आईसीएमडैंड्स को लागू करने के लिए एक अच्छा तरीका खोजने के लिए संघर्ष कर रहा हूं। मैं इस विषय के बारे में कुछ लेख पढ़ रहा हूं और मैंने नीचे एमएसडीएन से इस में टक्कर लगी है, जिसमें कहा गया है कि मुझे एसिंक वॉयड्स से बचना है क्योंकि इसे अनचाहे अपवादों को पकड़ना मुश्किल हो जाता है: http://msdn.microsoft.com/en-us/magazine/jj991977.aspx एक और प्रश्न में मैंने पूछा विषय, किसी ने यह भी कहा कि मुझे async voids का उपयोग नहीं करना चाहिए। घटनाओं के बिना।async/शून्य विधियों के बिना एमवीवीएम में प्रतीक्षा करें

लेकिन समस्या यह है कि इंटरनेट पर सभी उदाहरण मैं एसिंक वॉयड्स का उपयोग कर सकते हैं। http://richnewman.wordpress.com/2012/12/03/tutorial-asynchronous-programming-async-and-await-for-beginners/ और http://blog.mycupof.net/2012/08/23/mvvm-asyncdelegatecommand-what-asyncawait-can-do-for-uidevelopment/

पिछले एक async/का इंतजार है, लेकिन यह भी async रिक्तियों का उपयोग करता है का उपयोग कर ICommand के एक कार्यान्वयन है: यह दो लेख मैंने पाया उदाहरण हैं। मैं इस के लिए एक समाधान के साथ आने के लिए कोशिश कर रहा हूँ, इसलिए मैं RelayCommand के आधार पर ICommand के इस कार्यान्वयन लिखा है:

public delegate Task AsyncAction(); 

public class RelayCommandAsync : ICommand 
{ 
    private AsyncAction _handler; 
    public RelayCommandAsync(AsyncAction handler) 
    { 
     _handler = handler; 
    } 

    private bool _isEnabled; 
    public bool IsEnabled 
    { 
     get { return _isEnabled; } 
     set 
     { 
      if (value != _isEnabled) 
      { 
       _isEnabled = value; 
       if (CanExecuteChanged != null) 
       { 
        CanExecuteChanged(this, EventArgs.Empty); 
       } 
      } 
     } 
    } 

    public bool CanExecute(object parameter) 
    { 
     return IsEnabled; 
    } 

    public event EventHandler CanExecuteChanged; 

    public void Execute(object parameter) 
    { 
     ExecuteAsync(); 
    } 

    private Task ExecuteAsync() 
    { 
     return _handler(); 
    } 
} 

और मैं इस तरह इसका इस्तेमाल करने की कोशिश कर रहा हूँ: निर्माता में :

saveCommand = new RelayCommandAsync(SaveSourceAsync); 
तो

:

private async Task SaveSourceAsync() 
{ 
    await Task.Run(() => { Save(); }); 
} 

private void Save() 
{ 
    // Slow operation 
} 
समस्या

है कि मैं इस और किसी भी अन्य कार्यान्वयन मैं नहीं जानता कि के रूप में जो है के साथ सहज महसूस नहीं कर रहा हूँ है सर्वोत्तम और इष्टतम।

क्या कोई इस बात का कुछ प्रकाश दे सकता है कि मुझे इसका उपयोग कैसे करना चाहिए, अधिमानतः एमवीवीएम के साथ?

उत्तर

21

संदर्भित लेख में, मैं कहना है कि ICommand.Execute व्यावहारिक रूप से एक ईवेंट हैंडलर है किया था, तो यह "से बचने के async void" दिशानिर्देश से एक अपवाद पर विचार किया जाएगा:

यह पहली दिशानिर्देश संक्षेप में, आपको चाहिए Async शून्य को async कार्य को पसंद करें ... इस दिशानिर्देश का अपवाद असीमित घटना हैंडलर है, जो शून्य को वापस करना होगा। इस अपवाद में वे विधियां शामिल हैं जो तर्कसंगत ईवेंट हैंडलर हैं, भले ही वे सचमुच ईवेंट हैंडलर नहीं हैं (उदाहरण के लिए, ICOMand.Execute कार्यान्वयन)।

अपने ICommand कार्यान्वयन के बारे में, यह वास्तव में नहीं द्वारा एक दोष async void का उपयोग कर प्रस्तुत करता है: ICommand.Execute कार्यान्वयन इसके अपवाद को देख बिना Task छोड़ दी जाएगी। ताकि कार्यान्वयन async प्रतिनिधि द्वारा उठाए गए अपवादों को अनदेखा कर देगा।

इसके विपरीत, ब्लॉग पोस्ट से लिंक अपवाद यूआई तुल्यकालन संदर्भ के लिए प्रचार करने के लिए अनुमति देता है एक async void ICommand.Execute जो await रों Task है। जो - इस मामले में - वांछित व्यवहार है क्योंकि यह वही व्यवहार है जब आप एक सिंक्रोनस ICommand.Execute अपवाद उठाते हैं।

यदि आपके पास झुकाव है, तो मैं चाहता हूं कि आप ICommand या दो जो मैंने अपने AsyncEx library में संभावित भावी समावेशन के लिए लिखा है, को आजमाएं। first one आपके द्वारा पोस्ट किए गए ब्लॉग में से एक के समान ही एक साधारण कमांड है।second one रद्दीकरण, प्रगति रिपोर्टिंग और CanExecute के स्वचालित प्रबंधन सहित एक बहुत अधिक पूर्ण "एसिंक्रोनस कमांड" कार्यान्वयन है। मैं किसी भी प्रतिक्रिया की सराहना करता हूं।

+0

मैं आपकी lib और कार्यान्वयन में एक नज़र डाल रहा हूं। तो मुझे ब्लॉग पोस्ट के लिए आईसीओएमएंड कार्यान्वयन के साथ कुछ बताएं, यदि कोई अपवाद होता है तो क्या Windows Phone App.xaml में अनचाहे अपवाद ईवेंट को उठाया जाएगा? मैं बाद में इसका परीक्षण कर रहा हूं। –

+0

मैं 'SimpleAsyncCommand' में एक नज़र डाल रहा था, ऐसा लगता है कि यह मेरे उद्देश्यों के रूप में काम करता है, मैं बस जानना चाहता हूं: मेरा निष्पादन' executeAsync' कॉल करने वाला है यूआई संदर्भों में चल रहा है और मुझे करना होगा इस विधि के भीतर 'प्रतीक्षा टास्क.रुन' का उपयोग करें, है ना? क्या मैं इस तरह काम कर रहे अपवाद खो दूंगा? अगर नहीं, मुझे लगता है कि मैं तुम्हारी मुक्ति का उपयोग कर रहा हूँ! –

+0

'आईसीओएमएंड' से अपवादों को डब्ल्यूपी यूआई पर उठाया जाएगा, इसलिए उन्हें 'आवेदन' भेजा जाएगा। अनचाहे अपवाद '। UI निष्पादन पर 'ExecuteAsync' निष्पादित किया जाएगा (इसलिए आपका' async' प्रतिनिधि UI थ्रेड पर चलना शुरू कर देगा)। यदि आप उस आदेश के लिए काम करने के लिए अवरुद्ध कर रहे हैं तो आप 'प्रतीक्षा टास्क' रुन का उपयोग कर सकते हैं; यदि आपके पास अतुल्यकालिक काम है, तो आपको 'कार्य' रुन की आवश्यकता नहीं होगी और केवल 'प्रतीक्षा' का उपयोग कर सकते हैं। और यह वास्तव में अभी तक मेरे lib का हिस्सा नहीं है; आपको अभी स्रोत को कॉपी करना होगा। –

संबंधित मुद्दे