क्या कोई समझा सकता है कि await
फ़ंक्शन क्या करता है?
क्या कोई समझा सकता है कि await
फ़ंक्शन क्या करता है?
जवाबों:
उन्होंने कल पीडीसी में इस बारे में बात की थी!
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();
मूल रूप से, async
और await
कीवर्ड आपको यह निर्दिष्ट करने की अनुमति देते हैं कि एक पद्धति का निष्पादन सभी usages पर रोकना चाहिए await
, जो अतुल्यकालिक विधि कॉल को चिह्नित करता है, और फिर एक बार अतुल्यकालिक ऑपरेशन पूरा होने पर फिर से शुरू होता है। यह आपको एप्लिकेशन के मुख्य थ्रेड में एक विधि को कॉल करने और जटिल काम को असिंक्रोनस रूप से संभालने की अनुमति देता है, बिना थ्रेड्स और जॉइन को स्पष्ट रूप से परिभाषित करने या ब्लॉक करने के लिए।
यह yield return
एक IEnumerable उत्पादन विधि में एक बयान के लिए कुछ हद तक समान होने के रूप में सोचो । जब रनटाइम हिट होता है yield
, तो यह मूल रूप से विधि की वर्तमान स्थिति को बचाएगा, और उपज होने वाले मूल्य या संदर्भ को वापस कर देगा। अगली बार IEnumerator.MoveNext () को रिटर्न ऑब्जेक्ट (जिसे रनटाइम द्वारा आंतरिक रूप से उत्पन्न किया जाता है) पर कॉल किया जाता है, विधि की पुरानी स्थिति को स्टैक पर पुनर्स्थापित किया जाता है और निष्पादन अगली पंक्ति के साथ जारी रहता है yield return
जैसे कि हम कभी नहीं छोड़ेंगे तरीका। इस कीवर्ड के बिना, एक IEnumerator प्रकार को राज्य को संग्रहीत करने और पुनरावृति अनुरोधों को संभालने के लिए कस्टम-परिभाषित किया जाना चाहिए, जो वास्तव में बहुत जटिल हो सकते हैं।
इसी तरह, एक विधि के रूप में चिह्नित async
कम से कम एक होना चाहिए await
। ए पर await
, रनटाइम वर्तमान थ्रेड की स्थिति को बचाएगा और स्टैक को कॉल करेगा, अतुल्यकालिक कॉल करेगा, और अगले संदेश को संभालने और ऐप को उत्तरदायी बनाए रखने के लिए रनटाइम के संदेश लूप में वापस खोल देगा। जब एसिंक्रोनस ऑपरेशन पूरा हो जाता है, तो अगले शेड्यूलिंग अवसर पर, एस्किंक ऑपरेशन को कॉल स्टैक को वापस धकेल दिया जाता है और जारी रखा जाता है जैसे कि कॉल सिंक्रोनस था।
तो, ये दो नए कीवर्ड मूल रूप से अतुल्यकालिक प्रक्रियाओं के कोडिंग को सरल करते हैं, बहुत हद yield return
तक कस्टम एन्यूमरबल्स की पीढ़ी को सरल बनाते हैं । युगल कीवर्ड और थोड़ी पृष्ठभूमि के ज्ञान के साथ, आप एक पारंपरिक अतुल्यकालिक पैटर्न के सभी भ्रामक और अक्सर त्रुटि-प्रवण विवरणों को छोड़ सकते हैं। यह बहुत अधिक किसी भी इवेंट-संचालित GUI ऐप जैसे Winforms, WPF of Silverlight में शामिल होगा।
वर्तमान में स्वीकृत उत्तर भ्रामक है।
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
से बाहर निकल रहा काम करो()
await
हैं? मतलब अगर इसे UI थ्रेड से बुलाया जाए तो यह UI थ्रेड को 3 सेकंड के लिए ब्लॉक कर देगा? इस मॉडल का विचार ऐसी चीजों को करने से बचना है।
.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
और इसे कॉलबैक में भेज दिया, इसलिए रनटाइम के दौरान दूसरा उदाहरण पहले की तरह ही व्यवहार करेगा।
ऐसा प्रतीत नहीं हो सकता है कि यह आपको बहुत काम बचा रहा है, लेकिन जब अपवाद हैंडलिंग और सिंक्रनाइज़ेशन संदर्भ जैसी चीजों की बात आती है, तो संकलक वास्तव में आपके लिए बहुत अधिक भार उठा रहा है। अधिक के लिए, मैं स्टीफन क्लीरी की ब्लॉग श्रृंखला के बाद पूछे जाने वाले प्रश्न सुझाऊंगा ।
अगर मुझे इसे जावा में लागू करना होता तो यह कुछ इस तरह दिखाई देती:
/**
* @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");
}
}
}