नया C # प्रतीक्षा सुविधा क्या है? [बन्द है]


83

क्या कोई समझा सकता है कि awaitफ़ंक्शन क्या करता है?




Dotnetperls.com/async पर भी अच्छे उदाहरण हैं ।
मिलजेन मिकिक

मैं नहीं मानता कि यह प्रश्न बहुत व्यापक है या इसे बंद किया जाना चाहिए। यह पूछ रहा है कि एक कीवर्ड का मतलब क्या है। (पहले का संस्करण किसी तरह अलग था?)
पैंजरक्रिस

जवाबों:


62

उन्होंने कल पीडीसी में इस बारे में बात की थी!

Await का उपयोग .NET में कार्य (समानांतर प्रोग्रामिंग) के साथ संयोजन में किया जाता है। यह एक कीवर्ड है। इसे .NET के अगले संस्करण में पेश किया जा रहा है। यह कम या ज्यादा आपको टास्क को पूरा करने के लिए इंतजार करने के लिए एक विधि के निष्पादन को "रोक" देता है। यहाँ एक संक्षिप्त उदाहरण है:

//create and run a new task  
Task<DataTable> dataTask = new Task<DataTable>(SomeCrazyDatabaseOperation);

//run some other code immediately after this task is started and running  
ShowLoaderControl();  
StartStoryboard();

//this will actually "pause" the code execution until the task completes.  It doesn't lock the thread, but rather waits for the result, similar to an async callback  
// please so also note, that the task needs to be started before it can be awaited. Otherwise it will never return
dataTask.Start();
DataTable table = await dataTask;

//Now we can perform operations on the Task result, as if we're executing code after the async operation completed  
listBoxControl.DataContext = table;  
StopStoryboard();  
HideLoaderControl();

2
जब यह सी # वादों का रूप है: en.wikipedia.org/wiki/Futures_and_promises

12
थ्रेड की तरह बहुत कुछ लगता है। ()।
स्टीव गाइडी

10
की मुझे याद दिलाता है COMEFROM
योएल Spolsky

20
पूर्णता की खातिर, आइए जोड़ते हैं कि कोड के उपरोक्त टुकड़े को एक ऐसी विधि में लपेटा जाना चाहिए जो एक async कीवर्ड से सजी हो। जैसे ही पहले प्रतीक्षित कीवर्ड का सामना होता है, यह विधि तुरंत वापस आ जाएगी।
प्रेजेमेक

14
आपके शब्दों में: यह आपको विधि को "पॉज़" करने देता है, लेकिन यह ध्यान दिया जाना चाहिए कि यह थ्रेड को रोक या अवरुद्ध नहीं करता है।
मैट क्रिंकलाव-वोग

47

मूल रूप से, asyncऔर awaitकीवर्ड आपको यह निर्दिष्ट करने की अनुमति देते हैं कि एक पद्धति का निष्पादन सभी usages पर रोकना चाहिए await, जो अतुल्यकालिक विधि कॉल को चिह्नित करता है, और फिर एक बार अतुल्यकालिक ऑपरेशन पूरा होने पर फिर से शुरू होता है। यह आपको एप्लिकेशन के मुख्य थ्रेड में एक विधि को कॉल करने और जटिल काम को असिंक्रोनस रूप से संभालने की अनुमति देता है, बिना थ्रेड्स और जॉइन को स्पष्ट रूप से परिभाषित करने या ब्लॉक करने के लिए।

यह yield returnएक IEnumerable उत्पादन विधि में एक बयान के लिए कुछ हद तक समान होने के रूप में सोचो । जब रनटाइम हिट होता है yield, तो यह मूल रूप से विधि की वर्तमान स्थिति को बचाएगा, और उपज होने वाले मूल्य या संदर्भ को वापस कर देगा। अगली बार IEnumerator.MoveNext () को रिटर्न ऑब्जेक्ट (जिसे रनटाइम द्वारा आंतरिक रूप से उत्पन्न किया जाता है) पर कॉल किया जाता है, विधि की पुरानी स्थिति को स्टैक पर पुनर्स्थापित किया जाता है और निष्पादन अगली पंक्ति के साथ जारी रहता है yield returnजैसे कि हम कभी नहीं छोड़ेंगे तरीका। इस कीवर्ड के बिना, एक IEnumerator प्रकार को राज्य को संग्रहीत करने और पुनरावृति अनुरोधों को संभालने के लिए कस्टम-परिभाषित किया जाना चाहिए, जो वास्तव में बहुत जटिल हो सकते हैं।

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

तो, ये दो नए कीवर्ड मूल रूप से अतुल्यकालिक प्रक्रियाओं के कोडिंग को सरल करते हैं, बहुत हद yield returnतक कस्टम एन्यूमरबल्स की पीढ़ी को सरल बनाते हैं । युगल कीवर्ड और थोड़ी पृष्ठभूमि के ज्ञान के साथ, आप एक पारंपरिक अतुल्यकालिक पैटर्न के सभी भ्रामक और अक्सर त्रुटि-प्रवण विवरणों को छोड़ सकते हैं। यह बहुत अधिक किसी भी इवेंट-संचालित GUI ऐप जैसे Winforms, WPF of Silverlight में शामिल होगा।


31

वर्तमान में स्वीकृत उत्तर भ्रामक है। awaitकुछ भी विराम नहीं दे रहा है। सबसे पहले इसका उपयोग केवल उन विधियों या लैंबडैस के रूप में किया जा सकता है, जिन्हें आप asyncवापस भेजते हैं Taskया voidयदि आप Taskइस विधि में चल रहे उदाहरण का ध्यान नहीं रखते हैं ।

यहाँ एक उदाहरण है:

internal class Program
{
    private static void Main(string[] args)
    {
        var task = DoWork();
        Console.WriteLine("Task status: " + task.Status);
        Console.WriteLine("Waiting for ENTER");
        Console.ReadLine();
    }

    private static async Task DoWork()
    {
        Console.WriteLine("Entered DoWork(). Sleeping 3");
        // imitating time consuming code
        // in a real-world app this should be inside task, 
        // so method returns fast
        Thread.Sleep(3000);

        await Task.Run(() =>
            {
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine("async task iteration " + i);
                    // imitating time consuming code
                    Thread.Sleep(1000);
                }
            });

        Console.WriteLine("Exiting DoWork()");
    }
}

आउटपुट:

DoWork () में प्रवेश किया। सो रही है 3
async कार्य यात्रा 0
टास्क स्थिति: WaitingForActivation
प्रतीक्षा कर रहा है के लिए ENTER
कार्य async यात्रा 1
async कार्य यात्रा 2
async कार्य यात्रा 3
async कार्य यात्रा 4
async कार्य यात्रा 5
async कार्य यात्रा 6
async कार्य यात्रा 7
async कार्य यात्रा 8
async कार्य यात्रा 9
से बाहर निकल रहा काम करो()


1
आप यह भी जानते हैं कि यह फोन करने वाले को 3 सेकंड के लिए ब्लॉक कर देगा, इससे पहले कि वह उन्हें वह काम दे दे जो वे कर सकते awaitहैं? मतलब अगर इसे UI थ्रेड से बुलाया जाए तो यह UI थ्रेड को 3 सेकंड के लिए ब्लॉक कर देगा? इस मॉडल का विचार ऐसी चीजों को करने से बचना है।
सेवई

1
@ सर हाँ, यही बात थी। निष्पादन के सभी चरणों को दिखाने के लिए। यह वास्तविक दुनिया का उदाहरण नहीं है।
अरी

7
@ क्या आप मुझे ट्रोल कर रहे हैं?
अरी

2
नहीं। मैं आपके उत्तर को बेहतर बनाने में आपकी मदद करने की कोशिश कर रहा हूं।
सर्व

2
@ Anri ... मैं वास्तव में यहाँ आपके प्रयासों की सराहना करता हूँ। बहुत बहुत धन्यवाद!!
प्रवीण प्रजापति

11

.NET में अतुल्यकालिक प्रोग्रामिंग के लिए नए लोगों के लिए, यहां एक (पूरी तरह से नकली) सादृश्य है जिससे आप अधिक परिचित हो सकते हैं - AJAX जावास्क्रिप्ट / jQuery का उपयोग करके कॉल करता है। एक साधारण jQuery AJAX पोस्ट इस तरह दिखता है:

$.post(url, values, function(data) {
  // AJAX call completed, do something with returned data here
});

कारण हम कॉलबैक फ़ंक्शन में परिणाम संसाधित करते हैं, इसलिए हम AJAX कॉल के वापस आने के लिए प्रतीक्षा करते समय वर्तमान थ्रेड को ब्लॉक नहीं करते हैं। केवल जब प्रतिक्रिया तैयार होती है, तो कॉलबैक को निकाल दिया जाएगा, वर्तमान थ्रेड को अन्य समय में अन्य कार्य करने के लिए मुक्त कर देगा।

अब, यदि जावास्क्रिप्ट ने awaitकीवर्ड का समर्थन किया है (जो निश्चित रूप से यह नहीं है ( अभी तक! )), तो आप इसके साथ इसे प्राप्त कर सकते हैं:

var data = await $.post(url, values);
// AJAX call completed, do something with returned data here

यह एक बहुत क्लीनर है, लेकिन यह सुनिश्चित करता है कि हम सिंक्रोनस, ब्लॉकिंग कोड को पेश करते हैं। लेकिन नकली (नकली) जावास्क्रिप्ट कंपाइलर ने सबकुछ ले लिया awaitऔर इसे कॉलबैक में भेज दिया, इसलिए रनटाइम के दौरान दूसरा उदाहरण पहले की तरह ही व्यवहार करेगा।

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


इस नकली सादृश्य के साथ चिपके हुए (जिसने मुझे बहुत बड़ा सौदा करने में मदद की, इसलिए धन्यवाद!), क्या मतलब है "सब कुछ के बाद"? केवल एक ही फ़ंक्शन (विधि) के दायरे में सब कुछ? या सब कुछ के बाद के रूप में सब कुछ है कि कॉल स्टैक में जोड़ा जा सकता था के रूप में सब कुछ के बाद?

2
"सब कुछ के बाद" = शेष विधि। संकलक प्रभावी रूप से कॉलबैक के रूप में शेष विधि को फिर से लिखता है और नियंत्रण वर्तमान विधि के कॉलर को तुरंत लौटाता है।
टोड मेनियर

1
शानदार टोड, आपके स्पष्टीकरण के लिए फिर से धन्यवाद। दूसरों के लिए भी उपयोगी मुझे यकीन है।

-2

अगर मुझे इसे जावा में लागू करना होता तो यह कुछ इस तरह दिखाई देती:

/**
 * @author Ilya Gazman
 */
public abstract class SynchronizedTask{

    private ArrayList<Runnable> listeners = new ArrayList<Runnable>();

    private static final ThreadPoolExecutor threadPoolExecutor =  new ThreadPoolExecutor(6, 6, 0, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(1000));

    public final void await(Runnable listener){
        synchronized (this) {
            listeners.add(listener);
        }
    }

    public void excecute(){
        onExcecute();
        for (int i = listeners.size() - 1; i >= 0; i--) {
            Runnable runnable;
            synchronized (this) {
                runnable = listeners.remove(i);
            }
            threadPoolExecutor.execute(runnable);
        }
    }

    protected abstract void onExcecute();
}

आपका एप्लिकेशन इसका उपयोग इस तरह करेगा:

public class Test{
    private Job job = new Job();

    public Test() {
        craeteSomeJobToRunInBackground();
        methode1();
        methode2();
    }

    private void methode1(){
        System.out.println("Running methode 1");
        job.await(new Runnable() {

            @Override
            public void run() {
                System.out.println("Continue to running methode 1");
            }
        });
    }

    private void methode2(){
        System.out.println("Running methode 2");
    }

    private void craeteSomeJobToRunInBackground() {
        new Thread(new Runnable() {

            @Override
            public void run() {
                job.excecute();
            }
        }).start();
    }

    private class Job extends SynchronizedTask{

        @Override
        protected void onExcecute() {
            try {
                Thread.sleep(1000);
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Job is done");
        }
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.