जैसा कि आपने खोजा, वीएस 11 में कंपाइलर एक async Main
विधि को समाप्त कर देगा । यह Async CTP के साथ VS2010 में अनुमत (लेकिन कभी अनुशंसित नहीं) था।
मेरे पास हाल ही में async / प्रतीक्षा और विशेष रूप से अतुल्यकालिक कंसोल कार्यक्रमों के बारे में ब्लॉग पोस्ट हैं । यहाँ परिचय पोस्ट से कुछ पृष्ठभूमि जानकारी है:
यदि "वेटिट" देखता है कि प्रतीक्षा योग्य ने पूरा नहीं किया है, तो यह अतुल्यकालिक रूप से कार्य करता है। यह पूरी होने पर शेष विधि को चलाने के लिए प्रतीक्षा करने योग्य बताता है, और फिर async विधि से लौटता है। प्रतीक्षारत वर्तमान संदर्भ पर भी कब्जा कर लिया जाएगा जब यह शेष विधि को आवारा करने के लिए पारित करता है।
बाद में, जब प्रतीक्षा पूरी हो जाती है, तो यह एस्किंस पद्धति के शेष (कैप्चर किए गए संदर्भ के भीतर) को निष्पादित करेगा।
यहाँ क्यों यह सांत्वना कार्यक्रमों में एक समस्या है एक के साथ async Main
:
हमारे इंट्रो पोस्ट से याद रखें कि पूरा होने से पहले एक कॉल करने के लिए एक async विधि वापस आ जाएगी । यह पूरी तरह से यूआई अनुप्रयोगों में काम करता है (विधि सिर्फ यूआई इवेंट लूप में लौटती है) और एएसपी.नेट एप्लिकेशन (विधि थ्रेड से वापस आती है लेकिन अनुरोध को जीवित रखती है)। यह कंसोल प्रोग्राम के लिए इतनी अच्छी तरह से काम नहीं करता है: ओएस में मुख्य रिटर्न - इसलिए आपका प्रोग्राम बाहर निकलता है।
एक समाधान अपने स्वयं के संदर्भ प्रदान करने के लिए है - आपके कंसोल प्रोग्राम के लिए एक "मुख्य लूप" जो कि async- संगत है।
यदि आपके पास Async CTP वाली मशीन है, तो आप My Documents \ Microsoft Visual Studio Async CTP \ Samples (C # परीक्षण) यूनिट परीक्षण \ AsyncTestUtilitiesGeneralThreadAffineContext
से उपयोग कर सकते हैं । वैकल्पिक रूप से, आप मेरे Nito.AsyncEx NuGet पैकेज से उपयोग कर सकते हैं ।AsyncContext
यहां एक उदाहरण का उपयोग किया गया है AsyncContext
; GeneralThreadAffineContext
लगभग समान उपयोग है:
using Nito.AsyncEx;
class Program
{
static void Main(string[] args)
{
AsyncContext.Run(() => MainAsync(args));
}
static async void MainAsync(string[] args)
{
Bootstrapper bs = new Bootstrapper();
var list = await bs.GetList();
}
}
वैकल्पिक रूप से, आप केवल मुख्य कंसोल थ्रेड को ब्लॉक कर सकते हैं जब तक कि आपका एसिंक्रोनस काम पूरा नहीं हो जाता है:
class Program
{
static void Main(string[] args)
{
MainAsync(args).GetAwaiter().GetResult();
}
static async Task MainAsync(string[] args)
{
Bootstrapper bs = new Bootstrapper();
var list = await bs.GetList();
}
}
के उपयोग पर ध्यान दें GetAwaiter().GetResult()
; यह उस AggregateException
रैपिंग से बचा जाता है जो आपके उपयोग Wait()
या होने पर होता है Result
।
अद्यतन, 2017-11-30: विज़ुअल स्टूडियो 2017 अपडेट 3 (15.3) के अनुसार, भाषा अब एक समर्थन करती है async Main
- जब तक कि यह वापस आती है Task
या Task<T>
। तो अब आप यह कर सकते हैं:
class Program
{
static async Task Main(string[] args)
{
Bootstrapper bs = new Bootstrapper();
var list = await bs.GetList();
}
}
शब्दार्थ GetAwaiter().GetResult()
मुख्य धागे को अवरुद्ध करने की शैली के समान प्रतीत होता है । हालाँकि, अभी तक C # 7.1 के लिए कोई भाषा युक्ति नहीं है, इसलिए यह केवल एक धारणा है।