Task.Delay का उपयोग कब करें, थ्रेड का उपयोग कब करें। सोएं?


385

वहाँ अच्छा नियम (रों) जब उपयोग करने के लिए कर रहे हैं Task.Delay बनाम Thread.Sleep ?

  • विशेष रूप से, क्या एक के लिए दूसरे पर प्रभावी / कुशल होने के लिए न्यूनतम मूल्य है?
  • अंत में, चूंकि टास्क.डेले एक एसिक्स / प्रतीक्षित राज्य मशीन पर संदर्भ-स्विच का कारण बनता है, क्या इसका उपयोग करने का ओवरहेड है?

2
कंप्यूटर की दुनिया में 10ms का बहुत सा चक्र है ...
ब्रैड क्रिस्टी

कितनी तेजी से होना चाहिए? आपको क्या प्रदर्शन समस्याएं हैं?
LB

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

4
न्यूनतम 15.625 मिसे है, घड़ी अवरोध दर से कम मूल्यों का कोई प्रभाव नहीं है। Task.Delay हमेशा एक System.Threading.Timer, जलता है, नींद कोई उपरि है। आप ओवरहेड के बारे में चिंता नहीं करते हैं जब आप कोड लिखते हैं जो कुछ भी नहीं करता है।
हंस पसंत

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

जवाबों:


369

Thread.Sleepजब आप वर्तमान थ्रेड को ब्लॉक करना चाहते हैं तो उपयोग करें ।

Task.Delayजब आप वर्तमान थ्रेड को अवरुद्ध किए बिना एक तार्किक विलंब चाहते हैं, का उपयोग करें ।

इन विधियों के साथ दक्षता एक सर्वोपरि चिंता नहीं होनी चाहिए। उनका प्राथमिक वास्तविक दुनिया में उपयोग I / O संचालन के लिए पुनः प्रयास टाइमर के रूप में है, जो कि मिलीसेकंड के बजाय सेकंड के क्रम पर हैं।


3
यह एक ही प्राथमिक उपयोग का मामला है: एक रिट्री टाइमर।
स्टीफन क्लीयर

4
या जब आप CPU को मुख्य लूप में चबाना नहीं चाहते हैं।
एडी पार्कर

5
@RoyiNamir: नहीं। कोई "अन्य धागा" नहीं है। आंतरिक रूप से, यह एक टाइमर के साथ कार्यान्वित किया जाता है।
स्टीफन क्लीयर

20
दक्षता के बारे में चिंता न करने का सुझाव सलाह-मशविरा है। Thread.Sleepवर्तमान थ्रेड को ब्लॉक करेगा जो एक संदर्भ स्विच का कारण बनता है। यदि आप थ्रेड पूल का उपयोग कर रहे हैं, तो यह एक नया थ्रेड आवंटित करने का कारण भी बन सकता है। दोनों ऑपरेशन काफी भारी हैं, जबकि Task.Delayआदि द्वारा प्रदान की गई सहकारी मल्टी-टास्किंग को ओवरहेड से बचने, थ्रूपुट को अधिकतम करने, रद्द करने की अनुमति देने और क्लीनर कोड प्रदान करने के लिए डिज़ाइन किया गया है।
Corillian

2
एक वैकल्पिक onesi: I would use विधि के अंदर प्रतीक्षा करने के लिए @LucaCremry Thread.Sleep`। हालाँकि, मैं उत्पादन कोड में ऐसा कभी नहीं करता; मेरे अनुभव में, Thread.Sleepमैंने जो भी देखा है वह हर तरह के डिज़ाइन मुद्दे का संकेत है जो ठीक से तय किए जाने की आवश्यकता है।
स्टीफन क्लीयर

243

बीच सबसे बड़ा अंतर Task.Delayऔर Thread.Sleepहै कि है Task.Delayएसिंक्रोनस रूप से चलाने के लिए करना है। यह Task.Delayतुल्यकालिक कोड में उपयोग करने के लिए समझ में नहीं आता है । यह Thread.Sleepएसिंक्रोनस कोड में उपयोग करने के लिए एक बहुत बुरा विचार है ।

आम तौर पर आप कीवर्ड के Task.Delay() साथ कॉल करेंगे await:

await Task.Delay(5000);

या, यदि आप देरी से पहले कुछ कोड चलाना चाहते हैं:

var sw = new Stopwatch();
sw.Start();
Task delay = Task.Delay(5000);
Console.WriteLine("async: Running for {0} seconds", sw.Elapsed.TotalSeconds);
await delay;

लगता है कि यह क्या प्रिंट होगा? 0.0070048 सेकंड के लिए चल रहा है। यदि हम await delayइसके Console.WriteLineबजाय ऊपर जाते हैं, तो यह 5.0020168 सेकंड के लिए रनिंग प्रिंट करेगा।

आइए इसके अंतर को देखें Thread.Sleep:

class Program
{
    static void Main(string[] args)
    {
        Task delay = asyncTask();
        syncCode();
        delay.Wait();
        Console.ReadLine();
    }

    static async Task asyncTask()
    {
        var sw = new Stopwatch();
        sw.Start();
        Console.WriteLine("async: Starting");
        Task delay = Task.Delay(5000);
        Console.WriteLine("async: Running for {0} seconds", sw.Elapsed.TotalSeconds);
        await delay;
        Console.WriteLine("async: Running for {0} seconds", sw.Elapsed.TotalSeconds);
        Console.WriteLine("async: Done");
    }

    static void syncCode()
    {
        var sw = new Stopwatch();
        sw.Start();
        Console.WriteLine("sync: Starting");
        Thread.Sleep(5000);
        Console.WriteLine("sync: Running for {0} seconds", sw.Elapsed.TotalSeconds);
        Console.WriteLine("sync: Done");
    }
}

भविष्यवाणी करने की कोशिश करें कि यह क्या छपेगा ...

async: Async शुरू
: 0.0070048 सेकंड के लिए चल रहा है
सिंक:
Async शुरू : 5.0119008 सेकंड के लिए चल रहा है
async: पूर्ण
सिंक: 5.0020168 सेकंड के लिए चल रहा है
सिंक: पूर्ण

इसके अलावा, यह ध्यान रखना दिलचस्प है कि Thread.Sleepकहीं अधिक सटीक है, एमएस सटीकता वास्तव में एक समस्या नहीं है, जबकि Task.Delayन्यूनतम 15-30ms ले सकती है। दोनों कार्यों पर ओवरहेड एमएस सटीकता की तुलना में उनके पास न्यूनतम है ( Stopwatchयदि आपको कुछ अधिक सटीक आवश्यकता है तो कक्षा का उपयोग करें )। Thread.Sleepअभी भी अपने थ्रेड को टाई अप करें, Task.Delayजब आप प्रतीक्षा करते हैं तो अन्य काम करने के लिए इसे जारी करें।


15
यह "अतुल्यकालिक कोड में Thread.Sleep का उपयोग करने के लिए एक बहुत बुरा विचार" क्यों है?
सूर्यास्त

69
@sunside async कोड के प्रमुख लाभों में से एक यह है कि एक कॉल को एक ही बार में एक से अधिक कार्य करने से रोक दिया जाए, जिससे ब्लॉकिंग कॉल से बचा जा सके। यह बड़ी मात्रा में अलग-अलग थ्रेड्स की आवश्यकता को टालता है, और एक थ्रेडपुल को एक ही बार में कई अनुरोधों को पूरा करने की अनुमति देता है। हालाँकि, यह बताया गया है कि async कोड आमतौर पर थ्रेडपूल पर चलता है, अनावश्यक रूप से एक एकल थ्रेड को Thread.Sleep()एक पूरे थ्रेड के साथ अवरुद्ध करता है जो अन्यथा कहीं और उपयोग किया जा सकता है। यदि थ्रेड स्लीप () के साथ कई कार्य चलाए जाते हैं, तो सभी थ्रेडपूल थ्रेड्स को समाप्त करने और गंभीरता से बाधा प्रदर्शन करने का एक उच्च मौका है।
रयान

1
उसे ले लो। मैं asyncतरीकों के अर्थ में अतुल्यकालिक कोड की धारणा को याद कर रहा था क्योंकि उनका उपयोग करने के लिए प्रोत्साहित किया जाता है। यह मूल रूप Thread.Sleep()से एक थ्रेडपूल धागे में चलाने के लिए केवल एक बुरा विचार है , सामान्य रूप से बुरा विचार नहीं है। सब के बाद, वहाँ TaskCreationOptions.LongRunning(यद्यपि हतोत्साहित) Task.Factory.StartNew()मार्ग जा रहा है ।
सूर्यास्त

6
यशawait wait
एरिक वू

2
@Reyhn इस पर प्रलेखन यह है कि Tasl.Delayसिस्टम टाइमर का उपयोग करता है। चूँकि "सिस्टम क्लॉक" स्थिर दर पर "टिक" करता है। सिस्टम टाइमर की टिक स्पीड लगभग 16ms है, आपके द्वारा अनुरोध की गई किसी भी देरी को सिस्टम क्लॉक के कई टिकों पर राउंड किया जाएगा, पहले तक की भरपाई करें टिकटिक। Task.Delay Dd.microsoft.com/en-us/dotnet/api/… पर msdn प्रलेखन देखें और टिप्पणी करने के लिए नीचे स्क्रॉल करें।
डोरस

28

यदि वर्तमान थ्रेड मारा जाता है और आप उपयोग करते हैं Thread.Sleepऔर यह निष्पादित हो रहा है तो आपको मिल सकता है ThreadAbortException। साथ Task.Delayआप हमेशा एक रद्द टोकन प्रदान कर सकते हैं और शान से यह मार डालते हैं। एक कारण यह है कि मैं चुनूंगा Task.Delay। देख http://social.technet.microsoft.com/wiki/contents/articles/21177.visual-c-thread-sleep-vs-task-delay.aspx

मैं यह भी मानता हूं कि दक्षता इस मामले में सर्वोपरि नहीं है।


2
मान लें हम निम्नलिखित स्थिति है: await Task.Delay(5000)। जब मैं उस कार्य को मारता हूं जो मुझे मिलता है TaskCanceledException(और इसे दबा देता है) लेकिन मेरा धागा अभी भी जीवित है। साफ! :)
AlexMelw

24

मैं कुछ जोड़ना चाहता हूं। दरअसल, Task.Delayटाइमर आधारित वेट मैकेनिज्म है। यदि आप स्रोत को देखते हैं तो आपको एक Timerवर्ग का संदर्भ मिलेगा जो देरी के लिए जिम्मेदार है। दूसरी ओर Thread.Sleepवास्तव में सोने के लिए वर्तमान धागा बनाता है, इस तरह आप बस एक धागे को अवरुद्ध और बर्बाद कर रहे हैं। Async प्रोग्रामिंग मॉडल में आपको हमेशा उपयोग करना चाहिए Task.Delay()यदि आप कुछ देरी के बाद कुछ (निरंतरता) चाहते हैं।


'वेट टास्क। डेलय ()' थ्रेड को अन्य चीजों को करने के लिए तब तक मुक्त करता है जब तक टाइमर समाप्त नहीं हो जाता, 100% स्पष्ट। लेकिन क्या होगा अगर मैं 'प्रतीक्षा' का उपयोग नहीं कर सकता क्योंकि विधि 'async' के साथ उपसर्ग नहीं है? तब मैं केवल 'टास्क। डेलय ()' कह सकता हूं। उस स्थिति में धागा अभी भी अवरुद्ध है लेकिन मुझे विलंब () को रद्द करने का फायदा है । क्या वो सही है?
एरिक स्ट्रोकेन

5
@ErikStroeken आप थ्रेड और टास्क दोनों को कैंसेलेशन टोकन पास कर सकते हैं। Task.Delay ()। Wait। आप उस कार्य के साथ क्या करते हैं यह आपके ऊपर है, लेकिन धागा जारी है।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.