दिलचस्प पोस्ट
जावा का उपयोग करके एक फ़ाइल का नाम बदलें बेस 64 के लिए बाइनरी (डेल्फी) "कोई ऐसी फाइल या निर्देशिका नहीं" त्रुटि जब एक द्विआधारी निष्पादित कैसे FTP कैसे फाइल FTP पर मौजूद है FtpWebRequest से पहले मैं डब्ल्यूपीएफ में डीपीआई कैसे प्राप्त करूं? जावा टाइमर बनाम निष्पादक सेवा? चयनित नोड, उसके लिंक, और उसके बच्चों को डी 3 बल निर्देशित ग्राफ़ में हाइलाइट करें एचएच: एमएम समय प्रारूप के मिलान के लिए नियमित अभिव्यक्ति session.connection () हाइबरनेट पर पदावनत? इनपुट के लिए नहीं मांग रहा है? तिथि और समय के बीच का अंतर w / आउट कार्य सप्ताह Excel INNER SQL सर्वर में बाएं जुड़ने के प्रदर्शन में शामिल हों I समान मूल नीति को दरकिनार करने के तरीके सी # में ढेर क्षमता File_get_contents का उपयोग करके एक फ़ाइल अपलोड करें

HttpClient.GetAsync (…) का इंतजार करते समय कभी रिटर्न नहीं देता / async

संपादित करें: यह प्रश्न ऐसा लगता है कि यह एक ही समस्या हो सकती है, लेकिन इसमें कोई प्रतिक्रिया नहीं है …

संपादित करें: परीक्षण के मामले में 5 कार्य WaitingForActivation स्थिति में फंस जाता है।

मुझे .NET 4.5 में System.Net.Http.HttpClient का उपयोग करते हुए कुछ अजीब व्यवहार का सामना करना पड़ता है – जहां कॉल के परिणाम का "प्रतीक्षा" (जैसे) httpClient.GetAsync(...) कभी भी वापस नहीं आएगा।

यह केवल कुछ परिस्थितियों में होता है जब नए async / प्रतीक्षा भाषा कार्यक्षमता और कार्य एपीआई का उपयोग करते हुए – कोड केवल हमेशा जारी रखने के दौरान काम करता है।

यहाँ कुछ कोड है जो समस्या को पुन: उत्पन्न करता है – यह दृश्य प्राप्त करने के लिए विजुअल स्टूडियो 11 में एक नया "MVC 4 WebApi प्रोजेक्ट" ड्रॉप डाउन करें:

 /api/test1 /api/test2 /api/test3 /api/test4 /api/test5 <--- never completes /api/test6 

प्रत्येक समापन बिंदु यहाँ समान डेटा (stackoverflow.com से प्रतिक्रिया शीर्षकों) को छोड़कर /api/test5 को छोड़कर जो कभी भी पूर्ण नहीं होता है

क्या मुझे एचटीटीपी क्लाइंट क्लास में एक बग का सामना करना पड़ा, या क्या मैं किसी तरह एपीआई का दुरुपयोग कर रहा हूं?

पुन: उत्पन्न करने के लिए कोड:

 public class BaseApiController : ApiController { /// <summary> /// Retrieves data using continuations /// </summary> protected Task<string> Continuations_GetSomeDataAsync() { var httpClient = new HttpClient(); var t = httpClient.GetAsync("http://stackoverflow.com", HttpCompletionOption.ResponseHeadersRead); return t.ContinueWith(t1 => t1.Result.Content.Headers.ToString()); } /// <summary> /// Retrieves data using async/await /// </summary> protected async Task<string> AsyncAwait_GetSomeDataAsync() { var httpClient = new HttpClient(); var result = await httpClient.GetAsync("http://stackoverflow.com", HttpCompletionOption.ResponseHeadersRead); return result.Content.Headers.ToString(); } } public class Test1Controller : BaseApiController { /// <summary> /// Handles task using Async/Await /// </summary> public async Task<string> Get() { var data = await Continuations_GetSomeDataAsync(); return data; } } public class Test2Controller : BaseApiController { /// <summary> /// Handles task by blocking the thread until the task completes /// </summary> public string Get() { var task = Continuations_GetSomeDataAsync(); var data = task.GetAwaiter().GetResult(); return data; } } public class Test3Controller : BaseApiController { /// <summary> /// Passes the task back to the controller host /// </summary> public Task<string> Get() { return Continuations_GetSomeDataAsync(); } } public class Test4Controller : BaseApiController { /// <summary> /// Handles task using Async/Await /// </summary> public async Task<string> Get() { var data = await AsyncAwait_GetSomeDataAsync(); return data; } } public class Test5Controller : BaseApiController { /// <summary> /// Handles task by blocking the thread until the task completes /// </summary> public string Get() { var task = AsyncAwait_GetSomeDataAsync(); var data = task.GetAwaiter().GetResult(); return data; } } public class Test6Controller : BaseApiController { /// <summary> /// Passes the task back to the controller host /// </summary> public Task<string> Get() { return AsyncAwait_GetSomeDataAsync(); } } 

वेब के समाधान से एकत्रित समाधान "HttpClient.GetAsync (…) का इंतजार करते समय कभी रिटर्न नहीं देता / async"

आप एपीआई का दुरुपयोग कर रहे हैं

यहां स्थिति है: ASP.NET में, केवल एक धागा एक समय में एक अनुरोध को संभाल सकता है। यदि आवश्यक हो तो आप कुछ समांतर प्रसंस्करण कर सकते हैं (धागा पूल से अतिरिक्त धागे उधार लेना), लेकिन केवल एक थ्रेड में अनुरोध संदर्भ (अतिरिक्त सूत्रों का अनुरोध संदर्भ नहीं है) होगा

यह एएसपी.नेट SynchronizationContext कॉन्टैक्ट द्वारा प्रबंधित है ।

डिफ़ॉल्ट रूप से, जब आप किसी Task await करते हैं, तो विधि को एक कैप्चर किए गए SynchronizationContext TaskScheduler (या एक कैद किए गए TaskScheduler पर फिर से शुरू TaskScheduler , यदि कोई SynchronizationContext TaskScheduler नहीं है)। आम तौर पर, यह वही है जो आप चाहते हैं: एक एसिंक्रोनस नियंत्रक कार्रवाई कुछ का await करेगी, और जब इसे शुरू किया जाएगा, तो यह अनुरोध संदर्भ के साथ फिर से शुरू होगा

इसलिए, यहां क्यों test5 विफल रहता है:

  • Test5Controller.Get निष्पादित करता है (ASP.NET अनुरोध संदर्भ में)।
  • AsyncAwait_GetSomeDataAsync HttpClient.GetAsync निष्पादित करता है (ASP.NET अनुरोध संदर्भ में)।
  • HTTP अनुरोध भेजा जाता है, और HttpClient.GetAsync एक अपूर्ण Task
  • AsyncAwait_GetSomeDataAsync Task इंतजार कर रहा है; चूंकि यह पूरा नहीं हुआ है, AsyncAwait_GetSomeDataAsync एक अपूर्ण Task
  • Test5Controller.Get । उस Task पूरा होने तक मौजूदा थ्रेड को ब्लॉक कर दें।
  • HTTP प्रतिक्रिया आती है, और HttpClient.GetAsync द्वारा लौटा गया Task पूरा हो गया है।
  • AsyncAwait_GetSomeDataAsync ASP.NET अनुरोध संदर्भ में फिर से शुरू करने का प्रयास करता है। हालांकि, उस संदर्भ में पहले से ही कोई सूत्र है: Test5Controller.Get में थ्रेड अवरुद्ध।
  • गतिरोध।

यहां पर अन्य लोगों का काम क्यों है:

  • ( test1 , test2 , और test3 ): Continuations_GetSomeDataAsync ASP.NET अनुरोध संदर्भ के बाहर , धागा पूल में जारी Continuations_GetSomeDataAsync अनुसूची करता है। यह अनुरोध संदर्भ को फिर से दर्ज किए बिना पूर्ण करने के लिए Continuations_GetSomeDataAsync द्वारा प्राप्त Task अनुमति देता है।
  • ( test6 और test6 ): चूंकि Task की प्रतीक्षा है , एएसपी.NET अनुरोध धागा अवरुद्ध नहीं है। यह AsyncAwait_GetSomeDataAsync को ASP.NET अनुरोध संदर्भ का उपयोग करने की अनुमति देता है जब यह जारी रखने के लिए तैयार है

और यहां सबसे अच्छी पद्धतियां हैं:

  1. आपकी "लाइब्रेरी" async विधियों में, जब भी हो सके ConfigureAwait(false) उपयोग करें। आपके मामले में, यह AsyncAwait_GetSomeDataAsync को var result = await httpClient.GetAsync("http://stackoverflow.com", HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);
  2. Task पर ब्लॉक न करें; यह सभी तरह से async नीचे है दूसरे शब्दों में, GetResult बजाय await का GetResult ( Task.Result और Task.Waitawait को भी await साथ बदला जाना चाहिए)

इस प्रकार, आपको दोनों लाभ मिलते हैं: निरंतरता ( AsyncAwait_GetSomeDataAsync विधि का शेष) एक मूल थ्रेड पूल थ्रेड पर चलाया जाता है जिस पर ASP.NET अनुरोध संदर्भ दर्ज नहीं किया जाता है; और नियंत्रक स्वयं async (जो अनुरोध थ्रेड को ब्लॉक नहीं करता है)।

अधिक जानकारी:

  • मेरे async / await पोस्ट का await , जिसमें संक्षिप्त विवरण शामिल हैं कि कैसे Task वालों के लिए SynchronizationContext कंटैन्टेक्स का उपयोग किया जाता है।
  • एसिंक / प्रतीक्षित सामान्य प्रश्न , जो संदर्भों के बारे में अधिक विस्तार में आता है। भी इंतजार, और UI, और deadlocks देखें! अरे मेरा! जो यहां लागू होता है यद्यपि आप एक यूआई के बजाय एएसपी.नेट में हैं, क्योंकि एएसपी.नेट SynchronizationContext एक समय में अनुरोध के संदर्भ में सिर्फ एक धागा को प्रतिबंधित करता है।
  • यह एमएसडीएन मंच पोस्ट
  • स्टीफन टौब इस डेडलॉक (यूआई का उपयोग करके) को डेमो करते हैं , और लुसियन विशिक्क भी

अपडेट 2012-07-13: इस उत्तर को एक ब्लॉग पोस्ट में शामिल किया गया

यहाँ से त्वरित तय करें लेखन के बजाय:

 Task tsk = AsyncOperation(); tsk.Wait(); 

प्रयत्न:

 Task.Run(() => AsyncOperation()).Wait(); 

या यदि आपको एक परिणाम की आवश्यकता है:

 var result = Task.Run(() => AsyncOperation()).Result; 

स्रोत से (उपरोक्त उदाहरण से मिलान करने के लिए संपादित):

AsyncOperation अब ThreadPool पर लागू किया जाएगा, जहां एक सिंक्रनाइज़ेशन कॉन्टैक्सट नहीं होगा, और AsyncOperation के अंदर उपयोग की जाने वाली continuations को इनवेकिंग थ्रेड पर वापस नहीं लगाया जाएगा।

मेरे लिए यह एक महान दृष्टिकोण की तरह दिखता है क्योंकि मुझे हर जगह ConfigureAwait करने का उपयोग नहीं करना होगा (जहां तक ​​मैं बता सकता हूं कि वह जीयूआई में उचित async व्यवहार को भी तोड़ सकता है), और न ही मुझे इसे सभी तरह से एसिंक करना पड़ता है मेरे आवेदन में (जो वर्तमान में एक विकल्प नहीं है)।

स्रोत से:

सुनिश्चित करें कि FooAsync विधि में प्रतीक्षा करने के लिए मार्शल को वापस संदर्भ में नहीं मिलता है। ऐसा करने का सबसे सरल तरीका थ्रेडपूल से अतुल्यकालिक कार्य को प्रारंभ करना है, जैसे कि टास्क में अभिविन्यास लपेटकर। उदाहरण के लिए, उदाहरण

int सिंक () {वापसी कार्य.रुण (() => लाइब्रेरी। एफयूएसिंक ())। परिणाम; }

FooAsync अब थ्रेडपूल पर लागू किया जाएगा, जहां एक सिंक्रनाइज़ेशन कॉन्टैक्ट नहीं होगा, और FooAsync के अंदर उपयोग की जाने वाली सुराग वापस थ्रेड पर सिंक्रनाइज़ेशन () को लागू नहीं करेगा।

मैं यहाँ देख रहा हूँ:

http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.taskawaiter(v=vs.110).aspx

और यहाँ:

http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.taskawaiter.getresult(v=vs.110).aspx

और देख रहा है:

इस प्रकार और उसके सदस्यों का उपयोग संकलक द्वारा उपयोग के लिए करना है

await संस्करण को देखते हुए काम करता है, और काम करने का 'सही' तरीका है, क्या आपको वास्तव में इस प्रश्न का उत्तर चाहिए?

मेरा वोट है: एपीआई का दुरुपयोग करना

ये दोनों स्कूल वास्तव में शामिल नहीं हैं I

यहां वह परिदृश्य है जहां आपको बस उपयोग करना है

  Task.Run(() => AsyncOperation()).Wait(); 

या ऐसा कुछ

  AsyncContext.Run(AsyncOperation); 

मेरे पास एक एमवीसी कार्रवाई है जो डेटाबेस लेनदेन विशेषता के अंतर्गत है I यह विचार (शायद) कुछ गलत होने पर कार्रवाई में किए गए सभी कार्यों को वापस रोल करने के लिए (शायद) था यह संदर्भ स्विचिंग की अनुमति नहीं देता है, अन्यथा लेन-देन रोलबैक या कमिट स्वयं को विफल करने जा रहा है।

पुस्तकालय मुझे चाहिए async है क्योंकि यह async को चलाने की उम्मीद है

एकमात्र विकल्प इसे एक सामान्य समन्वयन कॉल के रूप में चलाएं

मैं सिर्फ अपनी तरफ से कह रहा हूं