2016-05-13 11 views
6

मुझे कोई समस्या है जहां कोई कार्य पूरा हो रहा है, लेकिन वापस लौट रहा है। मेरे पास विभिन्न सर्वरों पर एक वेबसाइट और एक वेब सेवा है। वेबसाइट वेब सेवा पर कॉल करती है जो फ़ंक्शन myFunction() के साथ लाइब्रेरी का उपयोग करती है। यदि मैं वेब सेवा के सर्वर पर कंसोल ऐप से अपने फ़ंक्शन को कॉल करता हूं, तो यह अपेक्षित रूप से वापस आ जाएगा। हालांकि, जब मैं MyFunction() को कॉल करने के लिए वेबसाइट से वेब सेवा पर कॉल करता हूं, तो उसे "चरण 3" प्राप्त होगा, लेकिन "चरण 4" नहीं होगा। मेरे पास नीचे दिए गए कॉल का सरलीकृत संस्करण है।कार्य पूरा करने के बाद वापस लौटना नहीं

private string myFunction() 
{ 
    string myStr = myDoWork().GetAwaiter().GetResult(); 

    return myStr; 
} 

private async Task<string> myDoWork() 
{ 
    logger.Debug("Step 1"); 
    string answer = await aFunction(); 

    logger.Debug("Step 4"); 

    return answer; 
} 

public async Task<string> aFunction() 
{ 
    logger.Debug("Step 2"); 
    return await bFunction(CancellationToken.None); 
} 

AsyncLock myLock = new AsyncLock(); 
public Task<string> bFunction(CancellationToken cToken) 
{ 
    return Task.Run(
     async() => 
     { 
      using (await myLock(cToken)) 
      { 
       logger.Debug("Step 3"); 
       result = "Hello"; 
       return result; 
      } 
     }, 
     cToken); 
} 

मैं async के लिए नया हूं और प्रतीक्षा कर रहा हूं, इसलिए किसी भी मदद की सराहना की जाएगी।

+0

यदि संभव हो, तो 'myFunction() 'async भी होना चाहिए। यदि आप एसिंक कॉल पर अवरुद्ध करते हैं तो अजीब चीजें हो सकती हैं। साथ ही, 'कार्य 'रुन' व्यवसाय 'बीफंक्शन' में क्यों? –

+0

कोई कारण नहीं है कि 'चरण 4' यहां निष्पादित नहीं किया जाएगा – Jonesopolis

+0

@NateBarbettini मुझे नहीं पता कि टास्क.रुन सामान क्यों है। मैंने जितना संभव हो सके कोड को सरल बनाने की कोशिश की, लेकिन आपने मेरा ध्यान उस टुकड़े पर लाया जो इससे कोई फर्क नहीं पड़ता। मैं कोड का पुन: उपयोग कर रहा हूं जो एक तुल्यकालिक कार्य के लिए असीमित होने के लिए लिखा गया था। एसिंक सामान के बिना इसे सब कुछ दोबारा लिखना काफी उपक्रम होगा। –

उत्तर

5

यह लगभग निश्चित रूप से myFunction() में एक डेडलॉक है। चरण 4 को मुख्य थ्रेड पर निष्पादित करने के लिए निर्धारित किया गया है, लेकिन ऐसा नहीं हो सकता क्योंकि मुख्य थ्रेड GetResult() पर प्रतीक्षा कर रहा है। उच्चतम स्तर संभव से

private string myFunction() 
{ 
    string myStr = Task.Run(async() => await myDoWork()).Result; 

    return myStr; 
} 

private async Task<string> myDoWork() 
{ 
    logger.Debug("Step 1"); 
    string answer = await aFunction(); 

    logger.Debug("Step 4"); 

    return answer; 
} 

public async Task<string> aFunction() 
{ 
    logger.Debug("Step 2"); 
    return await bFunction(CancellationToken.None); 
} 

AsyncLock myLock = new AsyncLock(); 
public async Task<string> bFunction(CancellationToken cToken) 
{ 
    using (await myLock(cToken)) 
    { 
     logger.Debug("Step 3"); 
     result = "Hello"; 
     return result; 
    } 
} 

सामान्य तौर पर, Task.Run() should be called:

यह इस के करीब कुछ किया जाना चाहिए। चीजों को यथासंभव सिंक्रोनस रखें और कॉलर को यह तय करने दें कि क्या वे पृष्ठभूमि थ्रेड का उपयोग करना चाहते हैं।

+0

आपको बहुत बहुत धन्यवाद! यह तय है। –

+2

@JesseMcConahie बेहतर समाधान 'myFunction' async बनाने के लिए आपके कोड को ठीक कर रहा है और 'टास्क.रुन' और न ही' GetResult() ' –

+0

@ScottChamberlain का उपयोग नहीं करता है। –

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