2012-03-05 13 views
6

के भीतर एसिंक्रोनस विधियों से अपवादों को कैसे संभालें I Rx का उपयोग करके कुछ कार्यों को असंकालिक रूप से संसाधित करने की कोशिश कर रहा हूं, उदा।एक SelectMany कथन

var list = Enumerable.Range(0, 100) 
    .ToObservable() 
    .SelectMany(x => Observable.Start(() => { 
     Console.WriteLine("Processing {0} ...", x); 

     Thread.Sleep(100 * x % 3); 

     if (x > 90) { 
      Console.WriteLine("Procesing exception {0} > 90", x); 
      throw new Exception("Value too large"); 
     } 
     Console.WriteLine("Processing {0} completed.", x); 
     return x; 
    })) 
    .Subscribe(
     x => { Console.WriteLine("Next [{0}]", x); }, 
     e => { 
      Console.WriteLine("Exception:"); 
      Console.WriteLine(e.Message); 
     }, 
     () => { Console.WriteLine("Complete"); } 
    ); 

इस कोड के साथ मेरी समस्या यह है कि अपवाद ग्राहक को पास नहीं किया जाता है। तो, बहुत कोशिश करने के बाद मैंने छोड़ दिया और इस सरल सवाल से पूछने का फैसला किया:

SelectMany कथन के भीतर एसिंक्रोनस विधियों के भीतर उठाए गए अपवादों को आप कैसे संभालें?

बस इसे स्पष्ट करने के लिए, अंतिम कार्यान्वयन एक समेकित फ़ंक्शन कॉल है जो अपवाद फेंक सकता है या नहीं। लक्ष्य इसे ग्राहक को पास करना है ताकि इसे आगे संसाधित किया जा सके (विशिष्ट मामले में उपयोगकर्ता को एक संदेश दिखाया जाएगा)।

संपादित

मैं एक जवाब के लिए नीचे मेरी निष्कर्ष ले जाया गया, ताकि मैं इस सवाल का जवाब के रूप में चिह्नित कर सकते हैं। निजी तौर पर, मैं स्वयं जवाब देने से सहमत नहीं हूं ... लेकिन कभी-कभी कोई दूसरा रास्ता नहीं है, इसलिए इसके लिए खेद है।

+1

क्या इससे आपकी मदद का जवाब मिलता है? http: // stackoverflow।कॉम/प्रश्न/7210051/पकड़-अपवाद-जो-एक-सदस्यता-ऑन-ए-सब्सक्रिप्शन-ऑननेक्स्ट-एक्शन – user981225

+0

बिल्कुल ठीक नहीं है क्योंकि यह अपवाद को दबाता है, हालांकि, अगर कुछ भी बेहतर नहीं होता है तो वैपिंग विचार उपयोगी हो सकता है हालांकि, मुझे यकीन नहीं है कि रैपिंग मेरे परिदृश्य में काम करेगी क्योंकि मैं एकाधिक एसिंच्रोनस और समांतर कॉल से निपट रहा हूं ... लेकिन मैं जांच करूंगा, धन्यवाद। – AxelEckenberger

+0

@ user981225, धन्यवाद मूल्यवान साबित हुआ लेकिन उत्तर काफी सरल है, संपादन देखें। – AxelEckenberger

उत्तर

1

जवाब

असल कोड सही ढंग से काम करता है। हालांकि, डीबगर अपवादों पर टूट जाता है क्योंकि एसिंक ऑपरेशंस अभी भी पृष्ठभूमि में निष्पादित होते हैं - कम से कम वे जो पहले अपवाद होने पर पहले ही शुरू हो चुके थे। मुझे फेंक दिया! यदि आप डिबगर के बिना कोड चलाते हैं तो अपवाद निगल जाते हैं। इसलिए मुझे लगता है कि समस्या वास्तव में कंप्यूटर के सामने थी :-)

अभी भी Observable.Start पर कुछ स्पष्टीकरण जैसा मैंने माना - यह सही ढंग से - कि लागू होना चाहिए वास्तव में कुछ त्रुटि प्रबंधन लागू ... पृष्ठभूमि देखें।

पृष्ठभूमि

Observable.Start एक सुविधा की विधि एक async आपरेशन में एक समारोह/acion चालू करने के लिए Observable.ToAsync विधि का उपयोग करता है है। यदि आप विधि के कार्यान्वयन को देखते हैं तो आप देखेंगे कि यह अपवाद हैंडलिंग/अग्रेषण पहले से ही करता है।

public static Func<IObservable<TResult>> ToAsync<TResult>(this Func<TResult> function, IScheduler scheduler) { 
    if (function != null) { 
     if (scheduler != null) { 
      return() => { 
       AsyncSubject<TResult> asyncSubject = new AsyncSubject<TResult>(); 
       scheduler.Schedule(() => { 
        TResult result = default(TResult); 
        try { 
         result = function(); 
        } catch (Exception exception1) { 
         Exception exception = exception1; 
         asyncSubject.OnError(exception); 
         return; 
        } 
        asyncSubject.OnNext(result); 
        asyncSubject.OnCompleted(); 
       }); 
       return asyncSubject.AsObservable<TResult>(); 
      }; 
     } else { 
      throw new ArgumentNullException("scheduler"); 
     } 
    } else { 
     throw new ArgumentNullException("function"); 
    } 
} 
3

अपने ऑनर/ऑनकंपटेड संदेशों को अधिसूचनाओं में बदलने के लिए Materialize का उपयोग करें।

उदाहरण के लिए,

observable.SelectMany(x => Observable.Start(fn).Materialize())

आप त्रुटि/पूरा एक अधिसूचना में लिपटे मिल जाएगा, रेखा नीचे अपने वास्तविक सदस्यता बिंदु तरह से नियंत्रित किया जा करने के लिए के रूप में त्रुटि के लिए विरोध SelectMany अंदर समाप्त किया जा रहा ।

यह अधिकांश असिनक कॉल ऑपरेशंस के लिए उपयोगी है क्योंकि विधि या तो विफल हो जाती है या पूर्ण हो जाती है।

+0

+1 यदि आपके पास ऑपरेशन का कैस्केड है और अधिसूचना को एक सामान्य त्रुटि हैंडलर के माध्यम से धक्का देना चाहते हैं तो मटेरियलाइज दिलचस्प हो सकता है। अच्छा विकल्प, हालांकि कहा गया है ... दुख की बात यह है कि समस्या कंप्यूटर के सामने बैठी थी, सही उपकरण का उपयोग करने में सक्षम नहीं ... :-) – AxelEckenberger

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