2015-10-15 7 views
5

मैं SynchronizationContext पर कुछ स्पष्ट है, एक गतिरोध की तरह याद आ रही किया जाना चाहिए का इंतजार है, लेकिन मैं नहीं दिख रहा है क्यों ऐसा होता है, और समझ में नहीं आता मैं इसे कैसे बच सकते हैं ...Task.WaitAll async के साथ लटका हुआ है/कार्य

तो, एप्लिकेशन Azure WorkerRole है (अनिवार्य रूप से, जहां तक ​​मैं समझता हूं, यूआई के बिना सामान्य विंडोज ऐप)। आवेदन में, मैं कार्यों की एक संख्या है, और मेरे कोड के योजनाबद्ध संस्करण के निष्पादन समानांतर कोशिश कर रहा हूँ यह है:

private async Task DoJob() 
{ 
    await SomeIoOperation(); 
} 


public void MethodExecutedByWorkerRoleInAnInfiniteLoop() 
{ 
    Log("Start"); 
    Task.WaitAll(DoJob(), DoJob(), DoJob()); 
    Log("End"); 
} 

मेरे यहाँ विचार है कि हम डिफ़ॉल्ट SynchronizationContext के साथ यहां काम कर रहे हैं है, तो हम से बचना चाहिए डेडलॉक जो हमारे पास इसी तरह की स्थिति में होगा, उदाहरण के लिए, एएसपी.नेट।

हालांकि, कभी-कभी निष्पादन लटकता है - प्रारंभ लॉग है, अंत तक कार्यकर्ता भूमिका निभाने तक अंत तक नहीं है। स्वाभाविक रूप से, ऐसा कोई रास्ता नहीं है कि DoJob लंबे समय तक चल रहा हो। विचित्र रूप से, यह कार्यकर्ता की भूमिका शुरू होने के तुरंत बाद नहीं होता है - इसे तब तक सामान्य ऑपरेशन के दिन या सप्ताह लग सकते हैं जब तक वह लटकता न हो।

मैं कोड को बहुत सरल बना सकता हूं - शायद यह महत्वपूर्ण है कि SomeIoOperation में वास्तव में क्या होता है - लेकिन मुझे लगता है कि यह SynchronizationContext दुरुपयोग से संबंधित कुछ स्पष्ट है।

SomeIoOperation.ConfigureAwait(false) सहायता होगी? मैं इसका परीक्षण भी नहीं कर सकता, क्योंकि मुझे नहीं पता कि यह काम कर रहा है क्योंकि समस्या ठीक हो गई है, या अंततः कुछ और दिनों के बाद लटका दी जाएगी।

विचार?

+1

यह आलेख आपको इस कारण पर प्रबुद्ध करेगा http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html – Gusdor

+2

'लॉग (सिंक्रनाइज़ेशन कॉन्टेक्स्ट.क्यूरेंट) में जोड़ें; और यदि यह 'शून्य' नहीं है, आपको पता चलेगा कि आपको 'सिंक्रनाइज़ेशन कॉन्टेक्स्ट' के साथ कोई समस्या है। – i3arnon

+0

'DoJob' हमेशा कॉलिंग संदर्भ में सिंक्रनाइज़ करना चाहता है। इससे कोई फर्क नहीं पड़ता कि 'SomeIoOperation' किस संदर्भ का उपयोग करता है। – Gusdor

उत्तर

8

आप सिंक्रनाइज़ेशन कॉन्टेक्स्ट पर डेडलॉक में बिल्कुल गिरते हैं। बस WaitAll के बजाय WhenAll का उपयोग करें:

public async Task MethodExecutedByWorkerRoleInAnInfiniteLoop() 
{ 
    Log("Start"); 
    await Task.WhenAll(DoJob(), DoJob(), DoJob()); 
    Log("End"); 
} 

और सभी काम करेंगे।

+1

यह विधि लूप में निष्पादित की जाती है - कॉलर जानना चाहेगा कि विधि कब पूर्ण हो गई है। आईएमओ, इस संशोधन को 'कार्य' वापस करना चाहिए। – Gusdor

+0

धन्यवाद। मैं बस कार्य पर शून्य बदलना भूल गया। –

+0

लेकिन फिर मेरे लूप में मुझे 'MethodExecutedByWorkerRoleInAnInfiniteLoop() करना होगा। प्रतीक्षा करें() '- क्या यह डेडलॉक नहीं करेगा? जहां तक ​​मुझे पता है, 'माइक्रोसॉफ्ट.WindowsAzure.ServiceRuntime' में' RoleEntryPoint' का कोई async संस्करण नहीं है, इसलिए मैं कहीं भी अपने 'MethodExecutedByWorkerRoleInAnInfiniteLoop' का इंतजार नहीं कर पाऊंगा। –

संबंधित मुद्दे