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


125

मैं एक विधि लागू कर रहा हूं Task<Result> StartSomeTask()और विधि को कॉल करने से पहले ही परिणाम जानने के लिए हो सकता है। मैं एक टास्क <T> कैसे बनाऊं जो पहले ही पूरा हो चुका है?

यह मैं वर्तमान में कर रहा हूँ:

private readonly Result theResult = new Result();

public override Task<Result> StartSomeTask()
{
    var task = new Task<Result>(() => theResult);
    task.RunSynchronously(CurrentThreadTaskScheduler.CurrentThread);
    return task;
}

क्या कोई बेहतर समाधान है?


6
ध्यान दें, इस प्रश्न के उत्तर भी एक सादे कार्य (कोई <T>) बनाने के लिए ठीक काम करते हैं क्योंकि टास्क <T> टास्क से विरासत में मिला है।
टिम लोवेल-स्मिथ

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

जवाबों:


111
private readonly Result theResult = new Result();

public override Task<Result> StartSomeTask()
{
    var taskSource = new TaskCompletionSource<Result>();
    taskSource.SetResult(theResult);
    return taskSource.Task;
}

@DanielLobo आपको एक जवाब मिल सकता है यदि आप समझाते हैं कि आपकी आपत्ति क्या है
user2023861

1
क्या यह नीचे नहीं होना चाहिए जो सरल है और बहुत अधिक वोटों के साथ है? @ user2023861
डैनियल लोबो

203

.NET 4.5 को लक्षित करते समय आप इसका उपयोग कर सकते हैं Task.FromResult:

public static Task<TResult> FromResult<TResult>(TResult result);

एक असफल कार्य बनाने के लिए, का उपयोग करें Task.FromException:

public static Task FromException(Exception exception);
public static Task<TResult> FromException<TResult>(Exception exception);

.NET 4.6 Task.CompletedTaskअगर आपको एक गैर जेनेरिक की आवश्यकता है, तो जोड़ता है Task

public static Task CompletedTask { get; }

.NET के पुराने संस्करणों के लिए वर्कअराउंड:

  • जब आप Async टारगेटिंग पैक (या AsyncCTP) के साथ .NET 4.0 को लक्षित करते हैं, तो आप TaskEx.FromResultइसके बजाय उपयोग कर सकते हैं ।

  • Task.NET 4.6 से पहले गैर-जेनेरिक प्राप्त करने के लिए , आप इस तथ्य का उपयोग कर सकते हैं जो कि Task<T>व्युत्पन्न है Taskऔर बस कॉल करें Task.FromResult<object>(null)या Task.FromResult(0)


13
एक गैर जेनेरिक कार्य को वापस करने के लिए, टास्क.क्रोमस्कूल (0) की तरह कुछ का उपयोग करना बेहतर है। पैरामीटर के रूप में "अशक्त" का उपयोग कंपाइलर को भ्रमित कर सकता है जो सामान्य पैरामीटर को निर्धारित नहीं कर सकता है।
व्हाइली

अपवादों के बारे में क्या? Async विधियों को स्टेट मशीन में संकलित किया जाता है जो अपवादों को पकड़ता है और उन्हें दिए गए कार्य में बचाता है। यह पहली बार प्रतीक्षा करने से पहले कोड निष्पादन के लिए भी होता है। विधि लौटती कार्य। FromResult सीधे अपवाद फेंक सकते हैं।
रॉबर्ट वाइजन

@ RobertVažan एक दिलचस्प किनारे का मामला। यकीनन, यदि आप एक विधि से अपने ज्ञात परिणाम को प्राप्त कर रहे हैं और यह विधि अपवादों को फेंकती है तो एक दोष है जिसे ठीक करने की आवश्यकता है।
गूसडर

1
@ RobertVažan आप आसानी से अपनी खुद की FromExceptionविधि लिख सकते हैं , जो व्यवहार करता है FromResultलेकिन इसके बजाय एक दोषपूर्ण कार्य का प्रतिनिधित्व करता है। इस तरह की एक विधि बस अपनी त्रुटि के मामलों के लिए वापस आ सकती है यदि यह अपवाद के लिए महत्वपूर्ण है कि परिणामी कार्य में प्रतिनिधित्व किया जाए।
सेवाकाल

1
Task.FromException .NET 4.5 में उपलब्ध नहीं है ... मुझे लगता है कि इसे निर्दिष्ट किया जाना चाहिए।
STLLTTT

12

बिना रिटर्न वैल्यू वाले कार्यों के लिए .NET 4.6 ने Task.CompletedTask जोड़ा है ।

यह एक टास्क देता है जो पहले से ही TaskStatus.RanToCompletion में है। यह शायद हर बार एक ही उदाहरण देता है, लेकिन प्रलेखन आपको उस तथ्य पर भरोसा नहीं करने की चेतावनी देता है।



1

टास्क.जब बिना किसी पैरामीटर के कॉल करने से पूरा किया हुआ कार्य वापस आ जाएगा।

Task task = Task.WhenAll();

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