आप इस तरह है कि टुकड़ा refactor सकता है होता है।
outcome
को प्राप्त करने के तरीके के आधार पर, async/await
का उपयोग करके यह काम करने के लिए और अधिक कुशल तरीके हो सकते हैं। अक्सर आपके पास GetOutcomeAsync()
जैसा कुछ हो सकता है जो एक वेब सेवा, डेटाबेस या सॉकेट कॉल को प्राकृतिक तरीके से असीमित रूप से बना देगा, तो आप केवल var outcome = await GetOutcomeAsync()
करेंगे।
यह ध्यान रखना महत्वपूर्ण है कि WaitForItToWork
संकलक द्वारा भागों में विभाजित किया जाएगा और await
लाइन का हिस्सा असीमित रूप से जारी रहेगा। Here's शायद आंतरिक रूप से यह कैसे किया जाता है पर सबसे अच्छा स्पष्टीकरण। बात यह है कि, आमतौर पर आपके कोड के किसी बिंदु पर आपको एसिंक कार्य के परिणाम पर सिंक्रनाइज़ करना होगा। उदा .:
private void Form1_Load(object sender, EventArgs e)
{
Task<bool> task = WaitForItToWork();
task.ContinueWith(_ => {
MessageBox.Show("WaitForItToWork done:" + task.Result.toString()); // true or false
}, TaskScheduler.FromCurrentSynchronizationContext());
}
आप बस इस किया जा सकता है:
private async void Form1_Load(object sender, EventArgs e)
{
bool result = await WaitForItToWork();
MessageBox.Show("WaitForItToWork done:" + result.toString()); // true or false
}
कि हालांकि Form1_Load
एक async विधि भी होगा।
[अद्यतन]
नीचे वर्णन करने के लिए करने के लिए क्या async/await
वास्तव में इस मामले में करता है मेरी प्रयास है। मैंने उसी तर्क के दो संस्करण बनाए, WaitForItToWorkAsync
(async/await
का उपयोग करके) और WaitForItToWorkAsyncTap
(TAP pattern का उपयोग async/await
के बिना)। फ्रिस्ट संस्करण काफी छोटा है, दूसरे के विपरीत। इस प्रकार, जबकि async/await
मोटे तौर पर संकलक की सिंटैक्टिक चीनी है, यह एसिंक्रोनस कोड को लिखने और समझने में बहुत आसान बनाता है।
// fake outcome() method for testing
bool outcome() { return new Random().Next(0, 99) > 50; }
// with async/await
async Task<bool> WaitForItToWorkAsync()
{
var succeeded = false;
while (!succeeded)
{
succeeded = outcome(); // if it worked, make as succeeded, else retry
await Task.Delay(1000);
}
return succeeded;
}
// without async/await
Task<bool> WaitForItToWorkAsyncTap()
{
var context = TaskScheduler.FromCurrentSynchronizationContext();
var tcs = new TaskCompletionSource<bool>();
var succeeded = false;
Action closure = null;
closure = delegate
{
succeeded = outcome(); // if it worked, make as succeeded, else retry
Task.Delay(1000).ContinueWith(delegate
{
if (succeeded)
tcs.SetResult(succeeded);
else
closure();
}, context);
};
// start the task logic synchronously
// it could end synchronously too! (e.g, if we used 'Task.Delay(0)')
closure();
return tcs.Task;
}
// start both tasks and handle the completion of each asynchronously
private void StartWaitForItToWork()
{
WaitForItToWorkAsync().ContinueWith((t) =>
{
MessageBox.Show("WaitForItToWorkAsync complete: " + t.Result.ToString());
}, TaskScheduler.FromCurrentSynchronizationContext());
WaitForItToWorkAsyncTap().ContinueWith((t) =>
{
MessageBox.Show("WaitForItToWorkAsyncTap complete: " + t.Result.ToString());
}, TaskScheduler.FromCurrentSynchronizationContext());
}
// await for each tasks (StartWaitForItToWorkAsync itself is async)
private async Task StartWaitForItToWorkAsync()
{
bool result = await WaitForItToWorkAsync();
MessageBox.Show("WaitForItToWorkAsync complete: " + result.ToString());
result = await WaitForItToWorkAsyncTap();
MessageBox.Show("WaitForItToWorkAsyncTap complete: " + result.ToString());
}
सूत्रण पर में कुछ जानकारी। यहां स्पष्ट रूप से बनाए गए कोई अतिरिक्त धागे नहीं हैं।आंतरिक रूप से, Task.Delay()
कार्यान्वयन पूल थ्रेड का उपयोग कर सकता है (मुझे संदेह है कि वे Timer Queues का उपयोग करते हैं), लेकिन इस विशेष उदाहरण (एक WinForms ऐप) में, await
के बाद निरंतरता उसी यूआई थ्रेड पर होगी। अन्य निष्पादन वातावरण (जैसे एक कंसोल ऐप) में, यह एक अलग थ्रेड पर जारी रह सकता है। स्टीफन क्लेरी द्वारा आईएमओ, this articleasync/await
थ्रेडिंग अवधारणाओं को समझने के लिए एक पढ़ा जाना चाहिए।
क्या मैं इसे 'यह कहकर बस कॉल करूंगा। WaitForItToWork();' - async लाइब्रेरी मेरे लिए थ्रेडिंग का ख्याल रखेगी? – Chris
आप इसे 'प्रतीक्षा करें। WaitForItToWork()' की तरह कॉल करेंगे, और कॉल की पूरी श्रृंखला को इसका समर्थन करने के लिए दोबारा प्रतिक्रिया दी जानी चाहिए ... मैं इसे और अधिक जानकारी शामिल करने के लिए अपने उत्तर पर विस्तृत करूंगा। – Noseratio
@ क्रिस: आपको "प्रतीक्षा" कीवर्ड का उपयोग करना याद रखना चाहिए। अंगूठे का नियम: हमेशा "प्रतीक्षा" को "async" फ़ंक्शन के साथ जोड़ा जाना चाहिए। तो, आपको प्रतीक्षा करें जैसे प्रतीक्षा करें WaitForItToWork(); –