जवाबों:
सबसे अच्छा अभ्यास async void
केवल फ़ंक्शन को चिह्नित करना है अगर यह आग है और भूल विधि है, यदि आप इंतजार करना चाहते हैं, तो आपको इसे चिह्नित करना चाहिए async Task
।
मामले में अगर आप अभी भी इंतजार करना चाहते हैं, तो इसे इस तरह से लपेटें await Task.Run(() => blah())
await Task.Run(() => An_async_void_method_I_can_not_modify_now())
await Task.Run(() => blah())
भ्रामक है। यह async फ़ंक्शन के पूरा होने का इंतजार नहीं करता है blah
, यह कार्य के (तुच्छ) निर्माण का इंतजार करता है, और blah()
पूरा होने से पहले ही जारी रहता है ।
Thread.Sleep
async नहीं है। यह सवाल एक async void
समारोह की प्रतीक्षा करने के बारे में है , कहते हैंasync void blah() { Task.Delay(10000); }
उपयोग करने के लिए सबसे अच्छा उपाय है async Task
। आपको async void
कई कारणों से बचना चाहिए , जिनमें से एक क्षमता है।
यदि विधि को वापस करने के लिए नहीं बनाया जा सकता है Task
(जैसे, यह एक घटना हैंडलर है), तो आप SemaphoreSlim
विधि संकेत का उपयोग कर सकते हैं जब यह बाहर निकलने वाला है। एक finally
ब्लॉक में ऐसा करने पर विचार करें ।
एक AutoResetEvent करते हैं, फ़ंक्शन को कॉल करते हैं और फिर AutoResetEvent पर प्रतीक्षा करते हैं और फिर इसे Async शून्य के अंदर सेट करते हैं जब आप जानते हैं कि यह हो गया है।
आप एक टास्क पर भी इंतजार कर सकते हैं जो आपके शून्य async से लौटता है
आपको वास्तव में मैन्युअल रूप से कुछ भी करने की आवश्यकता नहीं है, await
कीवर्ड blah()
रिटर्न तक फ़ंक्शन निष्पादन को रोक देता है।
private async void SomeFunction()
{
var x = await LoadBlahBlah(); <- Function is not paused
//rest of the code get's executed even if LoadBlahBlah() is still executing
}
private async Task<T> LoadBlahBlah()
{
await DoStuff(); <- function is paused
await DoMoreStuff();
}
T
ऑब्जेक्ट blah()
रिटर्न का प्रकार है
आप वास्तव में await
एक void
समारोह नहीं LoadBlahBlah()
कर सकते इसलिए ऐसा नहीं हो सकताvoid
LoadBlahBlah()
खत्म करने के लिए इंतजार करना चाहता हूं , न किblah()
मुझे पता है कि यह एक पुराना सवाल है, लेकिन यह अभी भी एक समस्या है जिसमें मैं घूमता रहता हूं, और फिर भी यह एक स्पष्ट समाधान नहीं है जब यह async का उपयोग करते समय सही ढंग से करने के लिए / एक async शून्य हस्ताक्षर विधि में प्रतीक्षा कर रहा हो।
हालांकि, मैंने देखा कि .Wit () शून्य विधि के अंदर ठीक से काम कर रहा है।
और चूंकि async शून्य और शून्य में एक ही हस्ताक्षर है, आपको निम्नलिखित कार्य करने की आवश्यकता हो सकती है।
void LoadBlahBlah()
{
blah().Wait(); //this blocks
}
भ्रामक रूप से पर्याप्त async / प्रतीक्षा अगले कोड पर ब्लॉक नहीं होती है।
async void LoadBlahBlah()
{
await blah(); //this does not block
}
जब आप अपना कोड हटाते हैं, तो मेरा अनुमान है कि async शून्य एक आंतरिक कार्य (async टास्क की तरह) बनाता है, लेकिन चूंकि हस्ताक्षर उस आंतरिक कार्य को वापस करने का समर्थन नहीं करता है
इसका मतलब यह है कि आंतरिक रूप से async शून्य विधि अभी भी आंतरिक रूप से async विधियों का "इंतजार" करने में सक्षम होगी। लेकिन आंतरिक टास्क पूरा होने पर बाहरी रूप से यह जानने में असमर्थ हैं।
तो मेरा निष्कर्ष यह है कि async शून्य उद्देश्य के रूप में काम कर रहा है, और यदि आपको आंतरिक टास्क से प्रतिक्रिया की आवश्यकता है, तो आपको इसके बजाय async टास्क हस्ताक्षर का उपयोग करने की आवश्यकता है।
उम्मीद है कि मेरा जुआ किसी को भी जवाब की तलाश में है।
संपादित करें: मैंने कुछ उदाहरण कोड बनाए और यह देखने के लिए विघटित किया कि वास्तव में क्या चल रहा है।
static async void Test()
{
await Task.Delay(5000);
}
static async Task TestAsync()
{
await Task.Delay(5000);
}
में बदल जाता है (संपादित करें: मुझे पता है कि निकाय कोड यहाँ नहीं है, लेकिन राज्य-कक्षों में है, लेकिन राज्य-कक्ष मूल रूप से समान थे, इसलिए मैंने उन्हें जोड़ने में कोई दिक्कत नहीं की)
private static void Test()
{
<Test>d__1 stateMachine = new <Test>d__1();
stateMachine.<>t__builder = AsyncVoidMethodBuilder.Create();
stateMachine.<>1__state = -1;
AsyncVoidMethodBuilder <>t__builder = stateMachine.<>t__builder;
<>t__builder.Start(ref stateMachine);
}
private static Task TestAsync()
{
<TestAsync>d__2 stateMachine = new <TestAsync>d__2();
stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create();
stateMachine.<>1__state = -1;
AsyncTaskMethodBuilder <>t__builder = stateMachine.<>t__builder;
<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
न तो AsyncVoidMethodBuilder या AsyncTaskMethodBuilder वास्तव में प्रारंभ विधि में कोई भी कोड है जो उन्हें ब्लॉक करने के लिए संकेत देगा, और वे शुरू होने के बाद हमेशा एसिंक्रोनस रूप से चलेंगे।
रिटर्निंग टास्क के बिना, यह जांचने का कोई तरीका नहीं होगा कि यह पूरा हो गया है या नहीं।
जैसा कि अपेक्षित था, यह केवल टास्क रनिंग async शुरू करता है, और फिर यह कोड में जारी रहता है। और Async टास्क, पहले यह कार्य शुरू करता है, और फिर इसे वापस लौटाता है।
इसलिए मुझे लगता है कि मेरा जवाब कभी भी एसिंक्स शून्य का उपयोग करने के लिए नहीं होगा, अगर आपको यह जानना आवश्यक है कि कार्य कब किया जाता है, तो यह है कि async टास्क के लिए क्या है।