2009-12-14 8 views
15

मैं एक डब्लूसीएफ सेवा से अपने मौजूदा व्यावसायिक तर्क के एक हिस्से का उपभोग करने के लिए एक सिल्वरलाइट प्रोग्राम को दोबारा लिख ​​रहा हूं। ऐसा करने में, मैंने सिल्वरलाइट 3 में प्रतिबंध में भाग लिया है जो केवल उन मामलों से बचने के लिए डब्ल्यूसीएफ सेवाओं को एसिंक्रोनस कॉल की अनुमति देता है जहां लंबे समय से चलने वाले या गैर-उत्तरदायी सेवा कॉल यूआई थ्रेड को अवरुद्ध करते हैं (एसएल के पास डब्ल्यूसीएफ सेवाओं का आह्वान करने के लिए एक दिलचस्प क्यूइंग मॉडल है यूआई थ्रेड पर)।कोरटाइन्स को लागू करने के लिए सी # इटरेटर्स का उपयोग करके (मिस) की समस्याएं

परिणामस्वरूप, जो एक बार सीधा था, लिखना तेजी से अधिक जटिल हो रहा है (मेरे प्रश्न के अंत में कोड उदाहरण देखें)।

आदर्श रूप में, मैं कार्यान्वयन को सरल बनाने के लिए coroutines का उपयोग करूंगा, लेकिन दुख की बात है कि, सी # वर्तमान में मूल भाषा सुविधा के रूप में कोरआउट को समर्थन नहीं देता है। हालांकि, सी # में yield return वाक्यविन्यास का उपयोग कर जेनरेटर (इटरेटर) की अवधारणा है। मेरा विचार है कि उपज कीवर्ड का पुन: उद्देश्य करना मुझे एक ही तर्क के लिए एक सरल कोरआउट मॉडल बनाने की अनुमति देना है।

मैं ऐसा करने में अनिच्छुक हूं, हालांकि, मुझे चिंता है कि कुछ छुपे हुए (तकनीकी) नुकसान हो सकते हैं जिनकी मुझे उम्मीद नहीं है (सिल्वरलाइट और डब्ल्यूसीएफ के साथ मेरे सापेक्ष अनुभवहीनता को देखते हुए)। मैं भी चिंतित हूं कि कार्यान्वयन तंत्र भविष्य के डेवलपर्स के लिए स्पष्ट नहीं हो सकता है और भविष्य में कोड को बनाए रखने या बढ़ाने के उनके प्रयासों को सरल बनाने के बजाय बाधा डाल सकता है। मैंने इस सवाल को एसओ पर राज्य मशीनों का निर्माण करने के लिए पुन: प्रयोजन करने के बारे में सोचा है: implementing a state machine using the "yield" keyword, और यह वही नहीं है जो मैं कर रहा हूं, यह मुझे रोक देता है।

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

कोड के मूल गैर WCF संस्करण इस तरह दिखता है:

void Button_Clicked(object sender, EventArgs e) { 
    using(var bizLogic = new BusinessLogicLayer()) { 
     try { 
      var resultFoo = bizLogic.Foo(); 
      // ... do something with resultFoo and the UI 
      var resultBar = bizLogic.Bar(resultFoo); 
      // ... do something with resultBar and the UI 
      var resultBaz = bizLogic.Baz(resultBar); 
      // ... do something with resultFoo, resultBar, resultBaz 
     } 
    } 
} 

फिर से सकारात्मक असर WCF संस्करण हो जाता है काफ़ी अधिक शामिल (यहां तक ​​कि अपवाद हैंडलिंग और पूर्व/पोस्ट हालत परीक्षण के बिना):

// fields needed to manage distributed/async state 
private FooResponse m_ResultFoo; 
private BarResponse m_ResultBar; 
private BazResponse m_ResultBaz; 
private SomeServiceClient m_Service; 

void Button_Clicked(object sender, EventArgs e) { 
    this.IsEnabled = false; // disable the UI while processing async WECF call chain 
    m_Service = new SomeServiceClient(); 
    m_Service.FooCompleted += OnFooCompleted; 
    m_Service.BeginFoo(); 
} 

// called asynchronously by SL when service responds 
void OnFooCompleted(FooResponse fr) { 
    m_ResultFoo = fr.Response; 
    // do some UI processing with resultFoo 
    m_Service.BarCompleted += OnBarCompleted; 
    m_Service.BeginBar(); 
} 

void OnBarCompleted(BarResponse br) { 
    m_ResultBar = br.Response; 
    // do some processing with resultBar 
    m_Service.BazCompleted += OnBazCompleted; 
    m_Service.BeginBaz(); 
} 

void OnBazCompleted(BazResponse bz) { 
    m_ResultBaz = bz.Response; 
    // ... do some processing with Foo/Bar/Baz results 
    m_Service.Dispose(); 
} 

ऊपर कोड स्पष्ट रूप से एक सरलीकरण, जबकि इसमें अपवाद हैंडलिंग, तुच्छता चेक, या अन्य ऐसी प्रथाओं उत्पादन कोड में आवश्यक होगा छोड़ देता है। फिर भी, मुझे लगता है कि यह जटिलता में तेजी से वृद्धि दर्शाता है जो सिल्वरलाइट में एसिंक्रोनस डब्ल्यूसीएफ प्रोग्रामिंग मॉडल के साथ शुरू होता है। मूल कार्यान्वयन को पुन: फैक्टरिंग (जिसने सेवा परत का उपयोग नहीं किया था, बल्कि एसएल क्लाइंट में इसके तर्क को एम्बेड किया था) तेजी से एक कठिन काम की तलाश में है। और एक जो काफी त्रुटि प्रवण होने की संभावना है।

कोड के सह नियमित संस्करण इस कुछ ऐसा दिखाई देगा (मैं अभी तक इस परीक्षण नहीं किया):

void Button_Clicked(object sender, EventArgs e) { 
    PerformSteps(ButtonClickCoRoutine); 
} 

private IEnumerable<Action> ButtonClickCoRoutine() { 
    using(var service = new SomeServiceClient()) { 
     FooResponse resultFoo; 
     BarResponse resultBar; 
     BazResponse resultBaz; 

     yield return() => { 
      service.FooCompleted = r => NextStep(r, out resultFoo); 
      service.BeginFoo(); 
     }; 
     yield return() => { 
      // do some UI stuff with resultFoo 
      service.BarCompleted = r => NextStep(r, out resultBar); 
      service.BeginBar(); 
     }; 
     yield return() => { 
      // do some UI stuff with resultBar 
      service.BazCompleted = r => NextStep(r, out resultBaz); 
      service.BeginBaz(); 
     }; 
     yield return() => { 
      // do some processing with resultFoo, resultBar, resultBaz 
     } 
    } 
} 

private void NextStep<T>(T result, out T store) { 
    store = result; 
    PerformSteps(); // continues iterating steps 
} 

private IEnumerable<Action> m_StepsToPerform; 
private void PerformSteps(IEnumerable<Action> steps) { 
    m_StepsToPerform = steps; 
    PerformSteps();   
} 

private void PerformSteps() { 
    if(m_StepsToPerform == null) 
     return; // nothing to do 

    m_StepsToPerform.MoveNext(); 
    var nextStep = m_StepsToPerform.Current; 
    if(nextStep == null) { 
     m_StepsToPerform.Dispose(); 
     m_StepsToPerform = null; 
     return; // end of steps 
    } 
    nextStep(); 
} 

चीजों के सभी प्रकार उपरोक्त कोड में सुधार करने की जरूरत है कि कर रहे हैं। लेकिन मूल आधार निरंतर पैटर्न (अपवाद हैंडलिंग और विभिन्न जांचों के लिए एक अवरोध बिंदु बनाने) को कारक करना है, जबकि प्रत्येक चरण के दौरान डब्ल्यूसीएफ के इवेंट-आधारित एसिंक मॉडल को ड्राइव करने की इजाजत दी जाती है - मूल रूप से जब अंतिम एसिंक डब्ल्यूसीएफ कॉल पूरा हो जाता है। सतह पर रहते हुए यह अधिक कोड जैसा दिखता है, यह उल्लेखनीय है कि PerformSteps() और NextStep() पुन: प्रयोज्य हैं, केवल ButtonClickCoRoutine() में कार्यान्वयन प्रत्येक अलग कार्यान्वयन साइट के साथ बदल जाएगा।

मुझे पूरा यकीन नहीं है कि मुझे यह मॉडल पसंद है, और अगर मैं इसे लागू करने के लिए एक आसान तरीका अस्तित्व में हूं तो मुझे आश्चर्य नहीं होगा।लेकिन मैं "इंटरवेब्स" या एमएसडीएन, या कहीं और किसी को खोजने में सक्षम नहीं हूं। मदद के लिए अग्रिम धन्यवाद।

+7

कोई अच्छा जवाब है, सिवाय इसके कि हम अपने दर्द महसूस कहने के लिए। हम चांदी के प्रकाश और अन्य ढांचे में एसिंक्रोनि का उपयोग कैसे करते हैं, इस बारे में बहुत सारे शोध कर रहे हैं। इटरेटर्स को सस्ता कोरआउटिन की तरह दिखने के लिए किए गए परिवर्तनों के प्रकार एक शुरुआत हैं, लेकिन इस जगह की सभी समस्याओं को हल करने के लिए पर्याप्त सामान्यता नहीं है। मैं निश्चित रूप से इस तरह के पैटर्न को भाषा में स्पष्ट रूप से व्यक्त करना चाहूंगा, साथ ही साथ हम इसे पुनरावर्तक पैटर्न के पीढ़ी (उपज) और खपत (foreach) पक्षों को स्पष्ट रूप से व्यक्त करते हैं। –

+0

मुझे लगता है कि यह प्रश्न एसिंक/सी # के लिए प्रतीक्षा करने के लिए प्रेरणा बताता है। –

उत्तर

11

आपको निश्चित रूप से Concurrency and Coordination Runtime पर देखना चाहिए। यह वास्तव में इस उद्देश्य के लिए iterators का उपयोग करता है।

दूसरी ओर, आपको Parallel Extensions और निरंतरता के लिए इसके दृष्टिकोण को भी देखना चाहिए। समानांतर एक्सटेंशन .NET 4.0 का हिस्सा है, जबकि सीसीआर को अलग-अलग लाइसेंसिंग की आवश्यकता होती है। मैं आपको उन लोगों द्वारा लिखे गए ढांचे के साथ जाने की सलाह देता हूं जो इस सामान को खाते हैं, सांस लेते हैं और सोते हैं। अपने आप को गलत जानकारी प्राप्त करना बहुत आसान है।

+0

मैं सहमत हूं। मेरी समझ यह थी कि सीसीआर के पास कुछ लाइसेंसिंग प्रतिबंध थे (जो कि अगर मैं उन्हें सही ढंग से समझता हूं तो मेरे लिए उपयोग करना असंभव हो जाएगा)। समांतर एक्सटेंशन लाइब्रेरी और .NET 4.0 वर्तमान में पूर्वावलोकन में है - मैंने उन्हें देखा है लेकिन मुझे इस तरह की चीज़ करने के लिए कोई कक्षा या सुविधाएं नहीं दिखाई देती हैं। क्या आपके मन में पीटीई का एक विशेष हिस्सा था? – LBushkin

+4

एलबुशकिन: आप प्रतिक्रियाशील एक्सटेंशन के हिस्से के रूप में समानांतर एक्सटेंशन को वापस भेज सकते हैं (लिंक के लिए मेरी पोस्ट देखें)। एक कार्य है। FromAsync विधि (+ अधिभार) जो आपको IAsyncResult- आधारित विधि जोड़ी से कार्य का निर्माण करने के साथ-साथ कार्य के साथ कार्य जारी रखता है। निरंतरता के लिए। –

+0

रीड: धन्यवाद। मैं उस पर एक नज़र डालूँगा। – LBushkin

4

Reactive Extensions for .NET इसे संभालने के लिए एक बहुत साफ मॉडल प्रदान करता है।

वे एक्सटेंशन प्रदान करते हैं जो आपको सरल, अधिक स्वच्छ तरीके से एसिंक्रोनस घटनाओं के खिलाफ सरल प्रतिनिधि लिखने देते हैं। मैं उन्हें देखने की सलाह देता हूं, और उन्हें इस स्थिति में अपनाना चाहता हूं।

+0

के हिस्से के रूप में एक मुफ्त डाउनलोड है, मैंने आरएक्स.NET को देखा है, हालांकि यह पूर्वावलोकन में है और शायद मेरे टाइमफ्रेम के लिए उपलब्ध नहीं होगा। मैं इस प्रकार के कोड RX.NET को लिखने के तरीके के बारे में भी अस्पष्ट हूं - मैंने उदाहरणों को देखा है जो ईवेंट स्रोतों को IObservable <> - अनिवार्य रूप से अनंत इटरेटर के रूप में व्यवहार करते हैं, लेकिन इस पैटर्न को कैसे व्यवस्थित नहीं करते हैं। क्या आप किसी भी उदाहरण के बारे में जानते हैं जिसे मैं देख सकता हूं? – LBushkin

+0

इस पर एक नज़र डालें: http://themechanicalbride.blogspot.com/2009/07/developing-with-rx-part-2-converting.html एक छोटी रैपिंग लाइब्रेरी की आवश्यकता है, लेकिन इसे निरंतरता के साथ विस्तारित करना आसान होगा। हालांकि, आरएक्स के साथ अवलोकनों से कार्यों को बनाने के लिए वहां कुछ नमूने हैं। –

+0

+1 आरएक्स सिल्वरलाइट में इस तरह की चीज लेने की दिशा है। मुझे आरएक्स की "पूर्वावलोकन" स्थिति के बारे में ज्यादा चिंता नहीं करनी चाहिए, अगर यह वास्तव में चिंता का विषय था तो शायद सिल्वरलाइट पूरी तरह से आपके लिए नहीं है। – AnthonyWJones

1

मैंने आपकी पूरी चीज़ नहीं पढ़ी।

वे सीसीआर रोबोटिक्स स्टूडियो में इस रणनीति का उपयोग करते हैं, और कई अन्य परियोजनाएं इस रणनीति का उपयोग करती हैं। LINQ का उपयोग करने का एक विकल्प है, उदाहरण देखें विवरण के लिए this blog। प्रतिक्रियाशील रूपरेखा (आरएक्स) इन लाइनों के साथ थोड़ी सी बनाई गई है।

लुका ने अपने PDC talk में उल्लेख किया है कि शायद सी #/वीबी का भविष्य संस्करण भाषा में एसिंक प्राइमेटिव जोड़ सकता है।

इस बीच, यदि आप एफ # का उपयोग कर सकते हैं, तो यह एक जीतने की रणनीति है। फिलहाल आप एफ # के साथ क्या कर सकते हैं यहां पानी से बाहर सबकुछ उड़ाता है।

संपादित

मेरे ब्लॉग से उदाहरण के शब्दों में, आप एक WCF ग्राहक है कि आप पर एक जोड़े तरीकों कॉल करना चाहते है लगता है। तुल्यकालिक संस्करण के रूप में

// a sample client function that runs synchronously 
let SumSquares (client : IMyClientContract) = 
    (box client :?> IClientChannel).Open() 
    let sq1 = client.Square(3) 
    let sq2 = client.Square(4) 
    (box client :?> IClientChannel).Close() 
    sq1 + sq2 

और इसी async कोड

// async version of our sample client - does not hold threads 
// while calling out to network 
let SumSquaresAsync (client : IMyClientContract) = 
    async { do! (box client :?> IClientChannel).OpenAsync() 
      let! sq1 = client.SquareAsync(3) 
      let! sq2 = client.SquareAsync(4) 
      do! (box client :?> IClientChannel).CloseAsync() 
      return sq1 + sq2 } 

कोई पागल कॉलबैक किया जाएगा लिखा जा सकता है, आप की तरह अगर-तो-और कुछ है, जबकि, कोशिश-अंत में नियंत्रण निर्माणों का उपयोग कर सकते हैं, इत्यादि, इसे लगभग लिखो जैसे आप सीधे लाइन कोड लिखते हैं, और सबकुछ काम करता है, लेकिन अब यह एसिंक है। दिए गए BeginFoo/EndFoo विधियों की जोड़ी लेना बहुत आसान है और इस मॉडल में उपयोग के लिए संबंधित F # async विधियां बनाएं।

+0

जैसा कि मैंने रीड और जॉन का जवाब दिया, मैंने सीसीआर, समांतर एक्सटेंशन और प्रतिक्रियाशील .NET को देखा है - हालांकि मैंने एक अच्छा उदाहरण नहीं देखा है कि मैं जो कर रहा हूं उससे संबंधित हूं। यह तय करने में मेरी मदद करने में एक लंबा सफर तय होगा कि इन पुस्तकालयों में से कौन सा (यदि कोई है) बिल फिट कर सकता है। – LBushkin

+0

क्या आपके पास एक एफ # उदाहरण है जिसे मैं देख सकता हूं? मुझे नहीं लगता कि मैं सिल्वरलाइट 3 एप में एफ # का उपयोग कर सकता हूं, लेकिन मैं इसका उपयोग करने वाले दृष्टिकोण से कुछ सीख सकता हूं। – LBushkin

+0

यहां 2008 से लुका की पीडीसी टॉक देखें: http://channel9.msdn.com/pdc2008/TL11/ वीडियो में, 50 मिनट में शुरू होने वाले लगभग 10 मिनट देखें, वह दिखाता है कि एसिंक कॉल करना कितना आसान है एफ # में आप सिल्वरलाइट 3 ऐप में एक एफ # लाइब्रेरी का उपयोग कर सकते हैं। – Brian

0

आप जेफरी रिचटर के असिनक्यूनेमेटर पर भी विचार करना चाहेंगे जो उनकी 'पावर थ्रेडिंग' लाइब्रेरी का हिस्सा है। उन्होंने सीसीआर विकसित करने के लिए सीसीआर टीम के साथ मिलकर काम किया। AsyncEnumerator जेसी के अनुसार सीसीआर की तुलना में अधिक 'हल्के वजन' के अनुसार है। व्यक्तिगत रूप से मैंने AsyncEnumerator के साथ खेला है लेकिन सीसीआर के साथ नहीं।

मैंने इसे क्रोध में उपयोग नहीं किया है - अब तक मुझे कोरआउटिन को बहुत दर्दनाक लागू करने के लिए गणनाकर्ताओं का उपयोग करने की सीमाएं मिली हैं। वर्तमान में एफ # सीखना क्योंकि अन्य चीजों के रूप में async वर्कफ़्लोज़ (यदि मुझे सही नाम याद है) जो ऐसा लगता है कि वे पूरी तरह से coroutines या 'निरंतरता' हैं (मैं सही नाम या शर्तों के बीच सटीक भेद भूल जाते हैं)।

वैसे भी, यहाँ कुछ लिंक है:

http://www.wintellect.com/PowerThreading.aspx

Channel 9 video on AsyncEnumerator

MSDN Article

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

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