2016-06-03 11 views
14

मैंने इसे थोड़ी देर के लिए आश्चर्यचकित कर दिया है, लेकिन वास्तव में कभी जवाब नहीं मिला।TaskCreationOptions.LongRunning का उपयोग कब करें?

मैं समझता हूँ कि यह कार्य अनुसूचक जहां काम पर चलेंगे के लिए एक संकेत है, और उस कार्य अनुसूचक (या आजकल? जाएगा) उस कार्य के लिए एक गैर-धागा पूल धागा का दृष्टांत का फैसला कर सकते हैं।

जो मुझे नहीं पता (और आश्चर्यजनक रूप से इंटरनेट पर कहीं भी नहीं मिल सकता है) कुछ कार्य को लंबे समय तक चलाने के लिए "अंगूठे का नियम" है। एक सेकंड लंबा है? 30 सेकंड? एक मिनट? 5 मिनट? क्या इसका उपयोग अनुप्रयोगों के उपयोग की मात्रा के साथ संबंध है? क्या मुझे प्रोग्रामर के रूप में थ्रेड पूल में # थ्रेड के साथ कुछ गणना करना चाहिए, मैं कितने कार्य बना सकता हूं, एक ही समय में कितने लंबे समय तक चलेंगे, और इस पर आधारित एक निर्णय लेना चाहिए कि लंबे समय तक चलने वाले कार्य का उपयोग करना है या नहीं?

यहां कुछ सीखने की उम्मीद है।

+0

ठीक है, यह 'ThreadPool.QueueUserWorkItem' और' नया थ्रेड 'के बीच चयन करने की आवश्यकता होने पर पूर्व' कार्य 'दुनिया जैसा ही है। –

+1

जानें [यह] (http://stackoverflow.com/a/13570611/1997232), [यह] (http://stackoverflow.com/a/13429164/1997232), [यह] (http: // stackoverflow। कॉम/q/7915947/+१९९७२३२)। अंगूठे के नियम के रूप में - 'LongRunning' का उपयोग न करें, जब तक कि यह वास्तव में लंबे समय तक चल रहा न हो (या तो आवेदन के समय के समान ही, उस के करीब या अपेक्षाकृत लंबी कार्य नौकरी पूरी होनी चाहिए)। – Sinatr

+0

कोई विशिष्ट मूल्य नहीं है। इस धागे को देखें: https://social.msdn.microsoft.com/Forums/en-US/8304b44f-0480-488c-93a4-ec419327183b/when-should-a-taks-be-cononsidered-longrunning?forum=parallelextensions – Dennis

उत्तर

10

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

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

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

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

+0

कार्य शेड्यूलर व्यवहार करने के तरीके के विस्तृत उत्तर के लिए बहुत बहुत धन्यवाद। अतिरिक्त धागे बनाए जाने पर निर्णय तर्क भी वास्तव में सहायक होता है और समय के मुद्दों को समझाता है जो हम पूरी तरह से चलते हैं। (कार्य को निष्पादित करने के लिए 1-2 सेकंड की देरी)। – bas

+1

क्या सभी I/O async वैसे भी नहीं होना चाहिए? I/O की प्रतीक्षा करते समय आप थ्रेड को क्यों अवरुद्ध करेंगे? क्या यह पूर्व-एसिंक/प्रतीक्षा दुनिया के लिए डिज़ाइन किया गया है? –

+0

मेह, कुछ प्रोग्रामर अपनी फ़ाइल हैंडलिंग कोड एसिंक बनाते हैं, डिस्क ड्राइव पर्याप्त तेज़ होते हैं। जब तक उन्हें मजबूर नहीं किया जाता है, जैसे वे WinRT में हैं। –

2

जब के रूप में लंबे समय से चल

यह निर्भर करता है कि क्या काम कर रहा है एक कार्य निर्दिष्ट करने के लिए। यदि कार्य में while(true) {...} है और एप्लिकेशन शटडाउन तक रहता है, तो LongRunning निर्दिष्ट करने के लिए यह समझ में आता है। यदि आप कतार पर कुछ ऑपरेशन करते हैं और वर्तमान थ्रेड को अवरुद्ध करने से रोकते हैं तो आपको वास्तव में परवाह नहीं है (कुछ भी निर्दिष्ट न करें)।

यह इस बात पर निर्भर करता है कि अन्य कार्य क्या कर रहे हैं। इससे कोई फर्क नहीं पड़ता कि आप LongRunning के साथ या उसके बिना कुछ कार्य चलाते हैं। लेकिन यह हजारों कार्यों को बनाने में एक समस्या हो सकती है, जहां प्रत्येक नई धागा मांगता है। या इसके विपरीत, आप इसे निर्दिष्ट किए बिना thread starvation अनुभव कर सकते हैं।

इसके बारे में सोचने का एक आसान तरीका यह है: क्या आप नए धागे में चलाने के लिए नया काम पसंद करते हैं या आपको परवाह नहीं है? यदि पहले - तो LongRunningOption का उपयोग करें। यह doesn't mean कोई अन्य थ्रेड में कौन सा कार्य चलाएगा, यह आपको एक अच्छा मानदंड है जब आपको इसे निर्दिष्ट करना होगा।

उदा। ContinueWith का उपयोग करते समय LongRunningExecuteSynchronously के विपरीत है (निर्दिष्ट होने से रोकने के लिए check है)। यदि आपके पास कई निरंतरताएं हैं, तो हो सकता है कि आप कतार के ऊपरी भाग से बचें और समान थ्रेड या विपरीत में विशिष्ट निरंतरता को चलाने के लिए चाहते हैं - आप नहीं चाहते कि निरंतरता दूसरों में हस्तक्षेप करे और फिर आप विशेष रूप से LongRunning का उपयोग कर सकें। ExecuteSynchronously के बारे में जानने के लिए this article (और this) देखें।

8

हंस के उत्तर में संशोधन जो मैं अधिकतर सहमत हूं।

LongRunning निर्दिष्ट करने का सबसे महत्वपूर्ण कारण व्यावहारिक रूप से गारंटीकृत और लगभग तत्काल निष्पादन प्राप्त करना है। थ्रेड पूल के लिए आपके काम आइटम में धागा जारी करने का कोई इंतजार नहीं होगा। मैं "व्यावहारिक रूप से" कह रहा हूं क्योंकि ओएस आपके धागे को निर्धारित करने के लिए स्वतंत्र नहीं है। लेकिन आपको सीपीयू का कुछ हिस्सा मिलेगा और आमतौर पर ऐसा होने तक बहुत लंबा समय नहीं लगेगा।

आप LongRunning निर्दिष्ट करके कतार के सामने कूद रहे हैं। लोड लोड होने पर थ्रेड पूल प्रति सेकंड 2 थ्रेड जारी करने की प्रतीक्षा करने की आवश्यकता नहीं है।

तो आप उन चीजों के लिए LongRunning का उपयोग करेंगे जो आवश्यक रूप से सबसे प्रभावी तरीके से नहीं बल्कि समय पर और स्थिर तरीके से होना चाहिए। उदाहरण के लिए, कुछ यूआई कार्य, गेम लूप, प्रगति रिपोर्टिंग, ...

CPU समय के 1ms के क्रम में थ्रेड लागतों को शुरू करना और रोकना। यह थ्रेड पूल कार्य आइटम जारी करने से कहीं अधिक है। मैंने बस 3 एम आइटम जारी किए और प्रति सेकंड पूरा होने के लिए इसे बेंचमार्क किया। बेंचमार्क काफी कृत्रिम था लेकिन परिमाण का क्रम सही है।

LongRunning एक संकेत होने के लिए प्रलेखित है लेकिन यह अभ्यास में बिल्कुल प्रभावी है। कोई ह्युरिस्टिक नहीं है जो आपके संकेत को ध्यान में रखता है। यह सही माना जाता है।

+1

वही लागू होता है, अतिरिक्त जानकारी और सुझावों के लिए धन्यवाद! विशेष रूप से वह हिस्सा जहां मैं सीखता हूं कि मुझे # धागे/कार्यों के साथ-साथ चलने के बारे में बहुत चिंता नहीं करनी चाहिए, लेकिन अधिक "क्या मैं एक कार्य शुरू कर रहा हूं जो समय पर फैशन शुरू कर दे! यह एक दिशानिर्देश है जो मुझे बहुत मदद करेगा – bas

1

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

कुछ लोग कह सकते हैं कि यह परिभाषा बहुत व्यापक है, कई कार्य लंबे समय तक चलेंगे, लेकिन इसके बारे में सोचें, भले ही प्रतीक्षा एक छोटे से समय सीमा तक सीमित हो, फिर भी कार्य CPU को प्रभावी ढंग से उपयोग नहीं कर रहा है। यदि इन कार्यों की मात्रा बढ़ जाती है, तो आप देखेंगे कि वे MinWorkerThreads (ThreadPool.SetMinThreads देखें) के पीछे रैखिक रूप से स्केल नहीं करते हैं, अवक्रमण वास्तव में खराब है।

सभी आई/ओ (फ़ाइल, नेटवर्क, डीबी, आदि) को एसिंक्रोनस के रूप में स्विच करने का दृष्टिकोण।

लंबे CPU-गहन कंप्यूटेशंस के कारण लंबे समय तक चलने वाले कार्य भी हैं।

दृष्टिकोण कुछ बिंदुओं पर await Task.Yield() डालने जैसे गणना को रोकना है, या दूसरे के बाद एक कार्य को शेड्यूल करके स्पष्ट रूप से गणना करना, प्रत्येक डेटा के पहले विभाजित हिस्से को संसाधित करना या एक बफर को सीमाबद्ध सीमा तक संसाधित करना है ।

निर्णय लेने के लिए "बहुत अधिक समय" आपके ऊपर है।

जब आप ऐसे वातावरण में हों जहां आप थ्रेड पूल साझा कर रहे हों, तो किसी भी समय बहुत अधिक समय होता है, आपको एक समझदार मूल्य चुनना होगा।

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

अधिक आम तौर पर, "बहुत अधिक समय" तब होता है जब कार्य आइटम संसाधित होने से तेज़ी से कतारबद्ध होते हैं। काम के विस्फोट हो सकते हैं, इसलिए आपको उस समय इकाई पर औसत देना चाहिए जो आपके लिए मायने रखता है, चाहे वह दूसरा हो, एक मिनट, 10 मिनट, आदि। जब आपके पास एसएलए हो, तो आपको यह अंतराल कहीं परिभाषित होना चाहिए।

एक समझदार मूल्य होने के बाद, आपको यह देखना चाहिए कि, यदि यह बढ़ाना ठीक है या आपको इसे कम करना है तो आपको देखना चाहिए। अधिकतर, यदि आप इसे बढ़ा सकते हैं, तो आप से बेहतर नहीं हैं, जब तक कि आप एक महत्वपूर्ण प्रदर्शन अंतर नहीं देख सकें। "महत्वपूर्ण" का अर्थ है संसाधित वस्तुओं की संख्या रैखिक रूप से अधिक बढ़ती है, इसलिए यदि यह रैखिक (या नीचे रैखिक, यह हो सकता है), तो ऐसा न करें।


मेरे अनुभव में, यदि आप इन परिभाषाओं में से किसी के द्वारा एक लंबी चलने वाली कार्य है, तो आप आमतौर पर अपने स्वयं के धागे के प्रबंधन या धागे के सेट के साथ बेहतर कर रहे हैं।

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