प्रारंभ को वादे-शैली के कार्य पर नहीं कहा जा सकता। अपवाद आ रहा है


108

मैं एक साधारण wpf डेस्कटॉप एप्लिकेशन बना रहा हूं। UI में एक बटन और कोड .cs फ़ाइल की तरह है।

private void Button_Click_2(object sender, RoutedEventArgs e)
{
    FunctionA();
}

public void FunctionA()
{
    Task.Delay(5000).Start();
    MessageBox.Show("Waiting Complete");
}

लेकिन आश्चर्यजनक रूप से लाइन Task.Delay(5000).Start();एक फेंक रहा है InvalidOperationException:

प्रारंभ को वादे-शैली के कार्य पर नहीं कहा जा सकता।

क्या कोई इस तरह से मदद कर सकता है?

जवाबों:


171

आपको वह त्रुटि मिल रही है क्योंकि Taskकक्षा ने आपको देने से पहले ही कार्य शुरू कर दिया था। आपको कभी भी केवल Startएक कार्य को कॉल करना चाहिए जिसे आप इसके निर्माता को कॉल करके बनाते हैं, और आपको यह भी नहीं करना चाहिए जब तक कि आपके पास कार्य को शुरू करने का एक अनिवार्य कारण नहीं है जब आप इसे बनाते हैं; यदि आप चाहते हैं कि यह अभी शुरू हो, तो आपको इसका उपयोग करना चाहिए Task.Runया Task.Factory.StartNewदोनों बनाने और एक नई शुरुआत करनी चाहिएTask

तो, अब हम जानते हैं कि बस उस pesky से छुटकारा पाने के लिए Start । आप अपना कोड चलाएंगे और पाएंगे कि संदेश बॉक्स तुरंत दिखाया गया है, न कि 5 सेकंड बाद, इसके साथ क्या हो रहा है?

खैर, Task.Delayबस आपको एक काम देता है जिसे 5 सेकंड में पूरा किया जाएगा। यह 5 सेकंड के लिए थ्रेड का निष्पादन बंद नहीं करता है। आप जो करना चाहते हैं, वह कुछ कोड है जिसे उस कार्य के पूरा होने के बाद निष्पादित किया जाता है। इसके ContinueWithलिए जो है। यह दिए गए कार्य को पूरा करने के बाद आपको कुछ कोड चलाने देता है:

public void FunctionA()
{
    Task.Delay(5000)
    .ContinueWith(t => 
    {
        MessageBox.Show("Waiting Complete");
    });
}

यह अपेक्षा के अनुरूप व्यवहार करेगा।

हम awaitनिरंतरता को और अधिक आसानी से जोड़ने के लिए C # 5.0 के कीवर्ड का लाभ उठा सकते हैं:

public async Task FunctionA()
{
    await Task.Delay(5000);
    MessageBox.Show("Waiting Complete");
}

जबकि यहाँ क्या हो रहा है, इसका पूरा विवरण इस प्रश्न के दायरे से बाहर है, अंतिम परिणाम एक विधि है जो पिछले पद्धति के समान है; आपके द्वारा विधि को कॉल करने के 5 सेकंड बाद यह एक संदेश बॉक्स दिखाएगा, लेकिन विधि स्वयं दोनों मामलों में तुरंत वापस आ जाएगी। उस ने कहा, awaitबहुत शक्तिशाली है, और हमें सरल और सरल प्रतीत होने वाले तरीकों को लिखने की अनुमति देता है, लेकिन यह ContinueWithसीधे लिखने का उपयोग करने के लिए बहुत कठिन और गड़बड़ होगा । यह बॉयलरप्लेट कोड का एक बहुत कुछ निकालते हुए, त्रुटि से निपटने से बहुत सरल करता है।



-4

जैसा कि सर्व ने कहा, कार्य पहले ही शुरू हो चुका है, इसलिए आप सभी को ऐसा करने के लिए इंतजार करना होगा (.Wait ()):

private void Button_Click_2(object sender, RoutedEventArgs e)
{
    FunctionA();
}
public void FunctionA()
{
    Task.Delay(5000).Wait();
    MessageBox.Show("Waiting Complete");
}

1
Wait()जब तक कार्य हल नहीं होता तब तक किसी कार्य को कॉल करना वर्तमान थ्रेड को ब्लॉक करेगा। यह लगभग कभी नहीं है कि आप क्या होना चाहते हैं।
जेरेमी

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