अतुल्यकालिक प्रोग्रामिंग और कम्प्यूटेशन एक्सप्रेशन

पिछले नोटों ( भाग I , भाग II ) में C # 5 में async / प्रतीक्षा के बारे में, मैंने लिखा कि Haskell, F # और Nemerle जैसी भाषाओं में एक समान दृष्टिकोण लागू किया जाता है, लेकिन, C # के विपरीत, ये भाषाएँ उच्च-स्तरीय अवधारणा का समर्थन करती हैं। जो आपको एसिंक्स की शैली में अतुल्यकालिक गणनाओं को लागू करने की अनुमति देता है / लाइब्रेरी के रूप में प्रतीक्षा करता है, और भाषा के स्तर पर नहीं। यह मजेदार है कि नेमेर्ले में यह अवधारणा खुद एक पुस्तकालय के रूप में लागू की गई है। इस अवधारणा का नाम मोनाड है। अतुल्यकालिक कंप्यूटिंग के अलावा, मोनड्स आपको अन्य अच्छाइयों को लागू करने की अनुमति देता है, जैसे कि सूची की समझ, निरंतरता, गंदे कार्यों को एक साफ ब्लॉक में बदलना, जिसके माध्यम से राज्य को घसीटा जाता है, और कई अन्य।



कुछ संन्यासी सी # प्रोग्रामर्स की ऐसी "इच्छाओं" को उपज संग्रहों के रूप में लागू करते हैं या लैम्बडा एक्सप्रेशन से उपज और उपज प्राप्त करते हैं।



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



शायद हर कोई जिसने महसूस किया है कि एक सन्यासी क्या है, एक सन्यासी के बारे में एक लेख लिख रहा है। मैं कोई अपवाद नहीं था। मैं विवरण को यथासंभव संक्षिप्त बनाने की कोशिश करूंगा ताकि जो लोग जानते हैं वे याद रखें, जबकि अन्य आगे के कथन को समझ सकें।



इकाई



मोनाड एक जेनेरिक पैटर्न है जिसका समर्थन भाषा में बनाया गया है। निम्नलिखित जोड़ी इस पैटर्न के कार्यान्वयन के केंद्र में है:



बहुरूपी प्रकार



interface F<T> { ... }
      
      





और उस पर ऑपरेशन के एक जोड़े



 class M { static public F<T> Return<T>(T obj) { ... } static F<U> Bind<T,U>(F<T> obj, Func<T, F<U>> fun) { ... } }
      
      





वापसी आपको एक मोनाड में किसी भी मूल्य को "लपेटने" की अनुमति देता है, और बिंद उस पर रूपांतरण करने के लिए। एक बहुत ही कमजोर सादृश्य StringBuilder के साथ तैयार किया जा सकता है, जिसमें हम कंस्ट्रक्टर पैरामीटर में प्रारंभिक मान पास करते हैं, और फिर इसे परिशिष्ट * विधियों के साथ बदलते हैं।



यदि आप F को IEnumerable से प्रतिस्थापित करते हैं, तो Bind हस्ताक्षर Linq SelectMany हस्ताक्षर जैसा दिखता है। यह आश्चर्य की बात नहीं है, क्योंकि लिनक महान आरक्षण के साथ, एक मठ भी है। संयोग से, बार्ट डी स्मेट ने इस बारे में PDC2010 में "LINQ, टेक टू - लिंकन को सब कुछ ड्रीम" ( लिंक ) की रिपोर्ट के साथ दिलचस्प रूप से बताया।



यदि लिनक एक सन्यासी है, तो एक सरल लाइनक अभिव्यक्ति बनाने की कोशिश करें:



 var nums = Enumerable.Range(-2, 7); var sqrt = from n in nums where n >=0 select Math.Sqrt(n);
      
      





एम-ऑपरेशन का उपयोग करना। सबसे पहले, एम-ऑपरेशन घोषित करें:



 static class MList { static public IEnumerable<T> Return<T>(T obj) { var list = new List<T>(); list.Add(obj); return list; } static public IEnumerable<U> Bind<T, U>(this IEnumerable<T> obj, Func<T, IEnumerable<U>> fun) { return obj.SelectMany(fun); } static public IEnumerable<T> Empty<T>() { return Enumerable.Empty<T>(); } }
      
      





और Linq अभिव्यक्ति को फिर से लिखना:



 var nums = Enumerable.Range(-2, 7); var sqrt = nums .Bind(n => n >= 0 ? MList.Return(n) : MList.Empty<int>()) .Bind(n => MList.Return(Math.Sqrt(n)));
      
      





यह लिनक से भी बदतर निकला, लेकिन इसका कारण यह है कि मोनड समर्थन सी # में नहीं बनाया गया है। निमेर्ल के मामले में, यह कोड निम्नानुसार हो सकता है, एम-ऑपरेशन की घोषणा करें:



 class MList { public Return[T](obj : T) : IEnumerable[T] { def data = List(); data.Add(obj); data } public Bind[T, U](obj : IEnumerable[T], f : T->IEnumerable[U]) : IEnumerable[U] { obj.SelectMany(f) } public Empty[T]() : IEnumerable[T] { Enumerable.Empty() } }
      
      





और Linq अभिव्यक्ति को फिर से लिखना:



 def mlist = MList(); def nums = Enumerable.Range(-2, 7); def sqrt = comp mlist { defcomp n = nums; defcomp n = if (n >= 0) mlist.Return(n) else mlist.Empty(); return Math.Sqrt(n :> double); };
      
      





सबसे पहले, याद रखें कि नेमेर्ले में हार C # में var का एक गैर-पोर्टेबल एनालॉग है, अगर एक टर्नरी ऑपरेटर ((:);) है और निर्माणकर्ता को कॉल करने के लिए नए की आवश्यकता नहीं है। अब इस बिंदु पर, कंप संचालक ने मोनडिक गणना की शुरुआत की घोषणा की, अगला पैरामीटर एम-ऑपरेशन प्रदान करता है, और फिर गणना स्वयं चलती है।



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



defcomp एक मैजिक ऑपरेटर है जो एक मोनाड (इस मामले में, टाइप IEnumerable [T]) को एक वैल्यू (टाइप T का) में बदल देता है, और इसके विपरीत, मान को मोनाड में बदल देता है। वास्तव में, कोई जादू नहीं है, सिर्फ एक अभिव्यक्ति है



 defcomp n = nums; ...
      
      





में संकलक द्वारा विस्तारित



 mlist.Bind(nums, n => ...)
      
      





अभिकलन भाव



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



इस समस्या का समाधान काफी सरल है, आपको एम-ऑपरेशन के तरीकों के सेट में जोड़ना होगा जो शाखा ऑपरेटरों और छोरों के परिवर्तन से निपटते हैं, उदाहरण के लिए, जबकि निम्नलिखित हस्ताक्षर होंगे:



 public F<FakeVoid> While<T>(Func<bool> cond, Func<F<FakeVoid>> body)
      
      





और जब कंपाइलर एक लूप का सामना करता है, जिसके शरीर में मोनैडिक ऑपरेटर होते हैं, तो यह पहले लूप बॉडी को एक Bind श्रंखला में बदल देता है, चूंकि Bind F <T> वापस आ जाता है, फिर इस चेन को एक लैम्ब्डा "() =" बॉडी () "में लपेटा जा सकता है, जैसे कि फंक <एफ <टी >>, संकलक भी लैंबडा में लूप की स्थिति को लपेटता है, और फिर इन लैंबडास को एम-ऑपरेशन जबकि।



प्रत्येक एम-ऑपरेशन को एक मोनाड वापस करना चाहिए, लेकिन लूप कुछ भी नहीं लौटाता है, इसलिए ऐसा कोई मूल्य नहीं है जिसे मोनाड में लपेटा जा सकता है। इन उद्देश्यों के लिए, फेकवॉइड प्रकार के एक सिंगलटन का उपयोग किया जाता है।



अब हम अभिकलन अभिव्यक्ति का एक अनौपचारिक विवरण दे सकते हैं, यह अनिवार्य भाषाओं के लिए एक मठ है। ए-ला हैस्केल के मामले में, कंपाइलर केवल डिफ्लैक को फिर से लिखता है और मोनैडिक गणना के अंदर वापस आता है, जैसा कि पहले से ही अनिवार्य भाषाओं के मामले में बताया गया है, नियंत्रण निर्माण भी फिर से लिखे गए हैं, नीचे दी गई तालिका में वे सभी ऑपरेटर हैं जो फिर से लिखे गए हैं:

defcomp मोनाड को अर्थ में विस्तारित करता है, जिसका अर्थ असाइनमेंट के करीब है
callcomp मान का उपयोग नहीं किया जाता है, जब मूल्य महत्वपूर्ण नहीं होता है
वापसी एक सनक में तर्क को लपेटता है, का उपयोग विमुद्रीकरण की गणना के ब्लॉक के अंत में किया जाता है, जिसका अर्थ किसी फ़ंक्शन से लौटने के करीब है
returncomp तर्क एक सन्यासी है, इस मोनाड को एक मानदिक गणनाओं के ब्लॉक के परिणामस्वरूप देता है, वापसी के विपरीत, इसे फिर से नहीं लपेटता है
उपज तर्क को एक सनक में लपेटता है और उपज वापसी के समान कार्य करता है
yieldcomp तर्क - सन्यासी, उपज वापसी के समान कार्य करता है, उपज के विपरीत तर्क को फिर से लपेटता नहीं है
अगर, जब, जब तक, करते हैं, का उपयोग करते हुए, foreach, का उपयोग करें ... अंत में ... पकड़ साधारण नियंत्रण संरचनाओं के विवादास्पद संस्करण


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



इंटरफेस का उपयोग नहीं करने का एक अन्य कारण यह है कि वे एम-ऑपरेशन के हस्ताक्षर पर अधिक कठोर स्थिति लगाते हैं। केवल मोनड्स और एम-ऑपरेशन की संगतता की आवश्यकता है। उदाहरण के लिए, ऊपर के उदाहरणों में यह मान लिया गया था कि मोनाड का एक सामान्य पैरामीटर है, लेकिन इसमें आसानी से उनमें से कई हो सकते हैं, आगे के कथन के लिए यह महत्वपूर्ण नहीं है, लेकिन कॉन्टिन्यूड मोनाड के उदाहरण का उपयोग करके इसका अध्ययन किया जा सकता है।



उन लोगों के लिए जो अपने स्वयं के बिल्डरों को लिखना चाहते हैं, सबसे अच्छी सलाह है कि कम्प्यूटेशन अभिव्यक्तियों के स्रोत का अध्ययन करें।



मानक बिल्डरों के उदाहरण





मानक बिल्डरों को कम्प्यूटेशन एक्सप्रेशन लाइब्रेरी में बनाया जाता है और एक पैरामीटर के रूप में उनकी आवृत्ति बनाने और कॉम्प को पास करने के बजाय, उनके नाम को एक पैरामीटर के रूप में पारित करने के लिए पर्याप्त है।



सूची


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



 def num = Enumerable.Range(-2, 7); def sqrt : list[double] = comp list { foreach(n in num) when(n >= 0) yield Math.Sqrt(n); }
      
      





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



अब एक और "विशलिस्ट" पर विचार करें - उपज संग्रह, शुरुआत में मैं एक स्थानीय फ़ंक्शन घोषित करता हूं जो एक अनुक्रम उत्पन्न करता है, और फिर मैं इसे दो बार कॉल करता हूं और उपज संग्रह करता हूं।



 def upTo(n) { comp list { for(mutable i=0;i<n;i++) yield i } } def twice = comp list { repeat(2) yieldcomp upTo(3); } Console.WriteLine(twice); //[0, 1, 2, 0, 1, 2]
      
      





मुझे अपना जनरेटर लिखना था, और टाइप के कारण "Enumerable.Range (0, 3)" का उपयोग नहीं करना चाहिए: यील्डकैप एक मोनड को इनपुट होने की उम्मीद करता है, इस मामले में इसका प्रकार सूची [int], और "Enumerable .ange (0, 3) है। "IEnumerable [int] देता है। इस विसंगति को दूर करने के लिए, एक और बिल्डर है - असंख्य।



गणनीय


यह बिल्डर काफी हद तक लिस्ट बिल्डर को दोहराता है, केवल IEnumerable [T] को एक प्रकार के मोनाड के रूप में उपयोग करता है और आपको अनंत अनुक्रम बनाने की अनुमति देता है। हम पिछले उदाहरण को फिर से लिखते हैं:



 def twice = comp enumerable { repeat(2) yieldcomp Enumerable.Range(0, 3); } foreach(item in twice) Console.Write($"$item "); //0, 1, 2, 0, 1, 2
      
      





सरणी


सूची और गणना योग्य की तरह, सरणी व्यवहार करता है, केवल मोन के प्रकार के रूप में सरणी [टी] का उपयोग करता है।



async


सबसे जटिल, लेकिन बहुत उपयोगी बिल्डर, कई मायनों में भविष्य के एसिंक्स / सी # में प्रतीक्षा करता है। इसका उपयोग अतुल्यकालिक कंप्यूटिंग के निर्माण के लिए किया जाता है, मौजूदा एसिंक्रोनस कंप्यूटिंग का संयोजन।



यह उपज और उपज के अलावा सभी कार्यों का समर्थन करता है।



इस बिल्डर का मोनड प्रकार Async [T] है। इस प्रकार की वस्तुएं अतुल्यकालिक गणना का वर्णन करती हैं, जिसके परिणामस्वरूप टाइप T का मान होगा (जैसे टास्क <T> C # में), यदि एसिंक्रोनस ऑपरेशन मान वापस नहीं करता है, तो T के बजाय एक विशिष्ट FakeVoid प्रकार का उपयोग किया जाता है। बाइंड ऑपरेशन, इसका प्रकार Async [T] * (T-> Async [U]) -> Async [U], फ़ंक्शन द्वारा "अतुल्यकालिक गणना (प्रकार Async [T])" जारी रखता है, यह फ़ंक्शन इनपुट के लिए टाइप T की एक वस्तु लेता है (परिणाम एसिंक्रोनस गणना) और एक नया एसिंक्रोनस प्रकार एसिंक्स [यू] की गणना करता है।



एक अन्य महत्वपूर्ण प्रकार अमूर्त वर्ग ExecutionContext है, इसके वंशज के उदाहरण एक अतुल्यकालिक ऑपरेशन शुरू करने के लिए जिम्मेदार हैं (उदाहरण के लिए, वर्तमान थ्रेड में, थ्रेडपूल से थ्रेड में, या सिंक्रोनाइज़ेशन कोड का उपयोग करके), यहाँ इसका हस्ताक्षर है:



 public abstract class ExecutionContext { public abstract Execute(computatuion : void -> void) : void; }
      
      





एक एसिंक्रोनस ऑपरेशन शुरू करने के लिए, आपको एसिंक्रोनस ऑपरेशन (क्लास Async [T]) का वर्णन करते हुए ऑब्जेक्ट की स्टार्ट विधि को कॉल करना होगा, इसे एक्सेक्युशनकॉनटेक्स्ट के ऑब्जेक्ट को पास करना है, यदि विधि को बिना किसी निर्णय के कहा जाता है, तो एसिंक्रोनस ऑपरेशन को ThreadPool.QueueUserWorkItem का उपयोग करके शुरू किया जाता है।



विस्तार (async CTP), जो आपको C # में async / प्रतीक्षा कार्यान्वयन का उपयोग करने की अनुमति देता है, पहले से ही कई विस्तार विधियां हैं जो अतुल्यकालिक संचालन के साथ मौजूदा कक्षाओं के पूरक हैं। Async पुस्तकालय के लिए इस तरह के विस्तार को मठ के कार्यान्वयन के साथ प्रदान नहीं करता है, लेकिन यह मौजूदा आदिम के आधार पर उन्हें बनाने का एक आसान तरीका प्रदान करता है। उदाहरण के लिए, मौजूदा HttpWebRequest हस्ताक्षर के हिस्से पर विचार करें, जो फ्रेमवर्क के पहले संस्करण से मौजूद अनुरोध को अतुल्यकालिक रूप से निष्पादित करने के लिए जिम्मेदार है:



 public class HttpWebRequest : WebRequest, ISerializable { public override IAsyncResult BeginGetResponse(AsyncCallback callback, object state); public override WebResponse EndGetResponse(IAsyncResult asyncResult); }
      
      





अब एक अतुल्यकालिक विस्तार बनाएं जो इन प्राइमेटिव्स का उपयोग करके मोनोएडिक कंप्यूटिंग में उपयोग के लिए उपयुक्त है।



 public module AsyncExtentions { public GetResponseAsync(this request : HttpWebRequest) : Async[WebResponse] { Async.FromBeginEnd(request.BeginGetResponse(_, null), request.EndGetResponse(_)) } }
      
      





यह याद किया जाना चाहिए कि नेमेर्ले में _ एक विशेष चरित्र है, इस मामले में इसके माध्यम से करी का उपयोग किया जाता है (अंकन च (_) x => f (x) के बराबर है)। इसी तरह, आप किसी भी मानक अतुल्यकालिक गणना के लिए रैपर बना सकते हैं।



उदाहरण के लिए, (C # 101) Async नमूनों से कुछ लिखने के लिए नेमेर्ले का उपयोग करने का प्रयास करें, उदाहरण के लिए, समानांतर में कई वेब पृष्ठों को लोड करना और शीर्षक को प्रिंट करना, मैंने GetHtml () और GetTitle () एक्सटेंशन कोड को छोड़ दिया, लेख पहले ही खींच लिया गया है।



 public PrintTitles() : Async[FakeVoid] { comp async { def response1 = HttpWebRequest.Create("http://www.ya.ru").GetResponseAsync(); def response2 = HttpWebRequest.Create("http://www.habr.ru").GetResponseAsync(); defcomp response1 = response1; defcomp response2 = response2; Console.WriteLine(response1.GetHtml().GetTitle()); Console.WriteLine(response2.GetHtml().GetTitle()); } }
      
      





पहली दो पंक्तियों में, अतुल्यकालिक पृष्ठ लोडिंग ऑपरेशन शुरू किए जाते हैं, ये विधियाँ निष्पादन के समय अतुल्यकालिक संचालन का वर्णन करने वाली वस्तुओं को वापस करती हैं, संकलक के दृष्टिकोण से इन वस्तुओं का प्रकार Async [WebResponce] (monad) है। अगली दो पंक्तियों में, अर्थ में मोनाड का विस्तार किया जाता है, अर्थ के एक और स्तर पर इसका अर्थ है परिणामों की अपेक्षा। अंतिम लाइनों में, परिणाम संसाधित होते हैं।



यह मजेदार है कि कैसे जावास्क्रिप्ट में सही तरीके से ( सभी अतुल्यकालिक कॉल के परिणामों की प्रतीक्षा करें) पर चर्चा बहुत गर्म हो गई: 90 पसंदीदा, 100 टिप्पणियाँ। लेकिन वापस हमारे उदाहरण पर।



याद रखने वाली मुख्य बात यह है कि एक मोनाड एक जेनेरिक पैटर्न है, आपने एक फ़ंक्शन बनाया है जो अतुल्यकालिक गणना का वर्णन करता है, लेकिन इसे शुरू नहीं करता है, आप इसे प्रिंटटाइक () प्रारंभ () प्रारंभ करें (GetResult) की तरह चला सकते हैं। वास्तव में, यह बहुत महत्वपूर्ण है, क्योंकि यह त्रुटियों का एक स्रोत हो सकता है, यदि विधि Async [T] को वापस करती है, तो आपको इस बारे में पता होना चाहिए कि क्या यह कोड गणना शुरू करता है या केवल उनका निर्माण करता है । भेद के लिए, यह संभवत: एक नामकरण सम्मेलन का उपयोग करने के लायक है, उदाहरण के लिए, कंप्यूटिंग शुरू करने वाले तरीकों में एक Async प्रत्यय होना चाहिए।



As # पर अपने दूसरे लेख / C # में प्रतीक्षारत, मैंने लिखा है कि इंतजार के लिए अतुल्यकालिक गणना के परिणाम को संसाधित करना शुरू कर देता है जो कि अतुल्यकालिक गणना शुरू करने वाले धागे के सिंक्रोनाइज़ेशन कॉन्टेक्स्ट में होता है। नेमेले इस संबंध में बहुत लचीलापन प्रदान करता है, गणना को एक धागे से दूसरे में स्थानांतरित करना संभव है। एक बटन क्लिक हैंडलर पर विचार करें:



 private button1_Click (sender : object, e : System.EventArgs) : void { def formContext = SystemExecutionContexts.FromCurrentSynchronizationContext(); def task = comp async { Thread.Sleep(5000); callcomp Async.SwitchTo(formContext); label1.Text = "success"; } _ = task.Start(SystemExecutionContexts.ThreadPool()); }
      
      





सबसे पहले हम एक एक्सकॉनियनकोटेक्स्ट प्राप्त करते हैं, जो वर्तमान सिंक्रोनाइज़ेशन कॉन्टेक्स्ट में गणना शुरू करता है, फिर हम एसिंक्रोनस ऑपरेशन का वर्णन करते हैं: थ्रेड। स्लीप एक भारी गणना का अनुकरण करता है, थ्रेड के एक्ज़ीक्यूटिव रेफरेंस संदर्भ को स्विच करें और परिणाम प्रदर्शित करें। गणना खुद ExecutionContexts थ्रेड पूल में लॉन्च की गई है।



यह जादू की तरह दिखता है, लेकिन वास्तव में यह सब पहले से ही हुआ था, कॉलकंप केवल मोनाड को प्रकट करता है जब इसका अर्थ महत्वपूर्ण नहीं होता है। लेकिन फिर इसका खुलासा क्यों? यह साइड इफेक्ट्स और राज्य की बात है, मोनैडिक ऑपरेशन के दौरान एक राज्य को उनके माध्यम से खींचा जाता है, उद्घाटन के समय मोनाड की इस राज्य तक पहुंच होती है और इसे बदल सकते हैं, जो कि यहां होता है। इस उदाहरण में, राज्य उस जानकारी को संग्रहीत करता है जिसमें संदर्भ को कोड निष्पादित किया जाना चाहिए, और यदि यह जानकारी बदल जाती है, तो यह नए संदर्भ में बदल जाती है। विवरण के लिए, मैं स्रोत को पढ़ने की सिफारिश कर सकता हूं, वे दिलचस्प हैं।



Async.SwitchTo के अलावा, अन्य दिलचस्प मोनड हैं जो निष्पादन के प्रवाह को प्रभावित करते हैं, उदाहरण के लिए, Async.Yield का कहना है कि निष्पादन संदर्भ बदल गया है, हालांकि यह इसे बदलता नहीं है। कुछ मामलों में, यह कुछ भी नहीं करता है, उस स्थिति में जब थ्रेडपूल का उपयोग किया गया था, यह क्रिया पूल से दूसरे थ्रेड के लिए कूद को उकसाती है।



निष्कर्ष



अंत में, मैं केवल यह ध्यान दे सकता हूं कि भिक्षु बहुत समृद्ध विषय हैं। इस लेख में, मैंने स्टेट, कॉन्ट (निरंतरता), शायद (एक और C # fanboy विशलिस्ट) जैसे क्लासिक साधुओं को नहीं छुआ। आप उनके बारे में अन्य लेखों में पढ़ सकते हैं, मैंने एक व्यावहारिक स्पष्टीकरण देने की कोशिश की, जिसकी बदौलत आप निनर्मल में अतुल्यकालिक प्रोग्रामिंग और सूची / अमूर्त साधनों का उपयोग शुरू कर सकते हैं और जान सकते हैं कि हुड के नीचे क्या हो रहा है।



कई मायनों में, भविष्य C # में प्रतीक्षा / async का कार्यान्वयन और नेमेरल में अतुल्यकालिक प्रोग्रामिंग के लिए राक्षसी दृष्टिकोण समान हैं, लेकिन प्रतीक्षा / async का समर्थन करने के लिए एक नोट है, भाषा के अगले संस्करण की आवश्यकता है, और नेमारल में अतुल्यकालिक प्रोग्रामिंग मोनड्स के माध्यम से कार्यान्वित की जाती है, जो बदले में मानक पुस्तकालय का हिस्सा है। भाषा, भाषा नहीं)।



मुझे टिप्पणी करने और प्रश्नों का उत्तर देने में खुशी होगी।



All Articles