एक पूर्ण कार्य बनाएँ


197

मैं एक पूर्ण Task(नहीं Task<T>) बनाना चाहता हूं । क्या ऐसा करने के लिए .NET में कुछ बनाया गया है?

एक संबंधित प्रश्न: एक पूरा कार्य बनाएँ <T>


2
It seems like the answer I'm getting from everyone is that using a garbage value like this is the correct way. That there isn't a way to do this without the garbage value is disappointing -- oh well.आपको क्या समस्या है? यदि आप एकल कैश करते हैं Taskतो आपका पूरा कार्यक्रम एक अतिरिक्त बिट मेमोरी लेता है। वह कुछ भी नहीं है । इसके अलावा, कोई ऐसा किए बिना एक पूरा कार्य बना सकता है, यह सिर्फ किसी भी बेहतर नहीं होगा।
14

10
ओह मेरी निराशा को अतिरिक्त मेमोरी का उपयोग करने से कोई लेना-देना नहीं है। यह सिर्फ इतना है कि कोड में कहीं भी कचरा मूल्य सुरुचिपूर्ण नहीं हैं।
तीमुथियुस

1
ध्यान दें कि आज ValueTaskपूर्ण कार्यों के लिए है (अर्थात आपके पास पहले से ही ऐसा कोड अनिवार्य रूप से समकालिक है), जो आपको आवंटन से बचाएगा।
नवाफल

जवाबों:


247

नेट (v4.6) का नवीनतम संस्करण सिर्फ इतना है कि जोड़ रहा है, एक अंतर्निहित Task.CompletedTask :

Task completedTask = Task.CompletedTask;

उस संपत्ति को एक नो-लॉक सिंगलटन के रूप में लागू किया जाता है ताकि आप लगभग हमेशा एक ही पूर्ण कार्य का उपयोग कर सकें।


1
बस नवीनतम वीएस 14 सीटीपी की जांच की और 4.5.3 परियोजना बनाई, Task.CompletedTaskअभी भी आंतरिक है।
पीटर रिची

1
2. या तो आपने नवीनतम CTP (जो 4 है और उस साइट से लिंक किया गया है) को डाउनलोड नहीं किया है या आपने संस्करण 4.5.3 निर्दिष्ट नहीं किया है। यहाँ मेरी मशीन पर क्या है । @PeterRitchie
i3arnon

मैंने Azure पर Visual Studio 14 की छवि से एक VM बनाया।
पीटर रिची


मैं मोनो 5.4.1.7 के साथ मैक ओएस एक्स पर काम कर रहा हूं और मुझे यही त्रुटि मिलती है। मैं इसे कैसे ठीक करूं?
खालिद अन्नजार

153

Task<T>संक्षेप में परिवर्तनीय है Task, इसलिए बस एक पूर्ण Task<T>(किसी भी Tऔर किसी भी मूल्य के साथ) प्राप्त करें और उसका उपयोग करें। आप इस तथ्य को छिपाने के लिए कुछ इस तरह का उपयोग कर सकते हैं कि वास्तविक परिणाम कहीं है।

private static Task completedTask = Task.FromResult(false);
public static Task CompletedTask()
{
    return completedTask;
}

ध्यान दें कि जब से हम परिणाम को उजागर नहीं कर रहे हैं, और कार्य हमेशा पूरा हो गया है, हम किसी एक कार्य को कैश कर सकते हैं और उसका पुन: उपयोग कर सकते हैं।

यदि आप .NET 4.0 का उपयोग कर रहे हैं और आपके पास नहीं है FromResultतो आप अपना स्वयं का उपयोग करके बना सकते हैं TaskCompletionSource:

public static Task<T> FromResult<T>(T value)
{
    var tcs = new TaskCompletionSource<T>();
    tcs.SetResult(value);
    return tcs.Task;
}

8
यदि आप 4.0 का उपयोग कर रहे हैं, तो आप Microsoft.Bcl.Async लाइब्रेरी को टास्कEx.FromResult, और साथ ही व्हॉट्सऐप
कार्ल

@Servy FromResult (गलत) और FromResult (सच) से क्या बदलता है?
फ्रांसेस्को बोनिज़ी

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

66

ऐसा करने के लिए मेरा पसंदीदा तरीका Task.WhenAll()बिना किसी तर्क के कॉल करना है। MSDN प्रलेखीकरण कहा गया है कि "आपूर्ति की सरणी / गणनीय कोई कार्य शामिल है, तो वापस आ काम से पहले ही फोन करने वाले के लिए वापस आ रहा है तुरंत एक RanToCompletion राज्य के लिए संक्रमण जाएगा।"। जैसा आप चाहते हैं वैसा ही लगता है।

अद्यतन: मुझे Microsoft के संदर्भ स्रोत पर स्रोत मिला ; वहाँ आप देख सकते हैं कि Task.WhenAll में निम्नलिखित शामिल हैं:

return (tasks.Length == 0) ? // take shortcut if there are no tasks upon which to wait
            Task.CompletedTask :
            new WhenAllPromise(tasks);

तो Task.CompletedTask वास्तव में आंतरिक है, लेकिन यह बिना किसी तर्क के व्हॉट्सऐप () पर कॉल करके उजागर होता है।


9
जबकि यह हैक की तरह महसूस करता है, यह डॉक्स से समर्थन किया है, इसलिए मुझे पता नहीं है, मुझे यह पसंद है!
सारा

2
मेरे लिए और मेरे .NET 4.5.2 विवश कोड के लिए यह काफी सुंदर है। धन्यवाद!
स्टास इवानोव

36

मैं उपयोग करूंगा Task.Delay(0)। आंतरिक रूप से, यह एक पूर्ण का कैश्ड उदाहरण देता है Task<T>। यह ठीक वैसा ही है जैसा कि वर्तमान उत्तर किसी भी तरह से करने का सुझाव देता है, केवल अब आपको अपने आप को एक उदाहरण नहीं देना है, और न ही आपके कोड में कोई अपात्र कचरा मूल्य है।

आप सोच रहे आप उपयोग कर सकते हैं हो सकता है Task.Yield()बजाय, लेकिन यह परिणाम की पता चला Task.Yield()है नहीं की एक उप-प्रकार Task, का परिणाम है, जबकि Task.Delay(0)है। यह दोनों के बीच के सूक्ष्म अंतरों में से एक है।


30

एक पूर्ण वापस करने के लिए आप Task.FromResult (.NET 4.5 में) का उपयोग कर सकते हैं Task<T>

यदि आपको एक गैर-जेनेरिक की आवश्यकता है Task, तो आप हमेशा उपयोग Task.FromResult(0)या समान कर सकते हैं , क्योंकि Task<T>एक उपवर्ग है Task


11

.Net के लिए 4.6 और इसके बाद के संस्करण का उपयोग करें

return Task.CompletedTask;

निचले संस्करण के लिए आप उपयोग कर सकते हैं

return new Task(() => { });

3
पूर्व 4.6 दृष्टिकोण के लिए, सावधान! आपको कार्य प्रारंभ करने की आवश्यकता है या यह कभी पूरा नहीं होगा! return Task.Delay(0);इसके बजाय का उपयोग कैसे करें ?
मिकेल


0

कैसा रहेगा:

#pragma warning disable 1998
    public async Task emptyTask() {
    }
#pragma warning restore 1998

यदि आप इसे बुरा नहीं मानते हैं तो आप चेतावनी दमन को छोड़ सकते हैं।


मेरा मानना ​​है कि एक विधि को चिह्नित करना asyncअभी भी पूरे राज्य मशीन तंत्र को बनाता है, भले ही आप इसका उपयोग न करें, इसलिए खाली कार्य को वापस करना कम-संसाधन परिदृश्यों के लिए अधिक कुशल है।
केल्विन फिशर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.