2013-07-25 23 views
7

मैं एक असिंक डेडलॉक में फंस गया हूं और मैं इसे ठीक करने के लिए सही वाक्यविन्यास नहीं समझ सकता। मैंने कई अलग-अलग समाधानों को देखा है, लेकिन समस्या का कारण बनने के बारे में काफी जानकारी नहीं मिल रही है।Async Await हैंडलर डेडलॉक

मैं बैकएंड के रूप में Parse का उपयोग कर रहा हूं और तालिका में लिखने के लिए हैंडलर का उपयोग करने की कोशिश कर रहा हूं।

public class VisitorSignupHandler : IHttpHandler 
{ 
    public void ProcessRequest(HttpContext context) 
    { 
     //Get the user's name and email address 
     var UserFullName = context.Request.QueryString["name"].UrlDecode(); 
     var UserEmailAddress = context.Request.QueryString["email"].UrlDecode(); 

     //Save the user's information 
     var TaskToken = UserSignup.SaveUserSignup(UserFullName, UserEmailAddress); 
     TaskToken.Wait(); 
     .... 

    } 

    public bool IsReusable { get { return false; } } 
} 

तो यह मेरे बीच स्तरीय बुला रहा है: मेरे हैंडलर तरह दिखता है

public static class UserSignup 
{ 
    public static async Task SaveUserSignup(string fullName, string emailAddress) 
    { 
     //Initialize the Parse client with the Application ID and the Windows key 
     ParseClient.Initialize(AppID, Key); 

     //Create the object 
     var UserObject = new ParseObject("UserSignup") 
          { 
           {"UserFullName", fullName}, 
           {"UserEmailAddress", emailAddress} 
          }; 

     //Commit the object 
     await UserObject.SaveAsync(); 
    } 
} 

हालांकि इस Wait() पर अटक जा रहा है। मैं इस धारणा के तहत था कि Wait() बस कार्य को पूरा करने की प्रतीक्षा करेगा, फिर सामान्य परिचालनों पर वापस आएं। क्या यह सही नहीं है?

उत्तर

13

आप एक सामान्य डेडलॉक समस्या में भाग रहे हैं जिसमें मैं on my blog और in a recent MSDN article का वर्णन करता हूं।

संक्षेप में, await डिफ़ॉल्ट रूप से कैप्चर किए गए "संदर्भ" और एएसपी.NET के अंदर async विधि फिर से शुरू करेगा, एक समय में केवल "थ्रेड" में केवल एक थ्रेड की अनुमति होगी। तो जब आप Wait पर कॉल करते हैं, तो आप उस संदर्भ के अंदर एक थ्रेड को अवरुद्ध कर रहे हैं, और awaitasync विधि को फिर से शुरू करने के लिए तैयार होने पर उस संदर्भ में प्रवेश नहीं कर सकता है। तो संदर्भ में धागा Wait पर 0 अवरुद्ध है (async विधि को पूरा करने के लिए प्रतीक्षा कर रहा है), और async विधि को संदर्भ के लिए प्रतीक्षा करने के लिए अवरुद्ध कर दिया गया है ... डेडलॉक।

इसे ठीक करने के लिए, आपको "सभी तरह से async" जाना चाहिए। इस मामले में, IHttpHandler के बजाय HttpTaskAsyncHandler का उपयोग करें:

public class VisitorSignupHandler : HttpTaskAsyncHandler 
{ 
    public override async Task ProcessRequestAsync(HttpContext context) 
    { 
    //Get the user's name and email address 
    var UserFullName = context.Request.QueryString["name"].UrlDecode(); 
    var UserEmailAddress = context.Request.QueryString["email"].UrlDecode(); 

    //Save the user's information 
    var TaskToken = UserSignup.SaveUserSignup(UserFullName, UserEmailAddress); 
    await TaskToken; 
    .... 

    } 
} 
+0

धन्यवाद! मैंने इसे पोस्ट करने से पहले अपने ब्लॉग को पढ़ा और सिंटैक्स को काफी समझ नहीं पाया। यह बहुत अच्छा काम करता है। इसकी प्रशंसा करना। –

+1

आपका स्वागत है! अनुलेख [टीएपी दस्तावेज] दें (http://msdn.microsoft.com/en-us/library/hh873175.aspx) एक अच्छा पढ़ा; कुछ 'async' सम्मेलन हैं जो विशेष रूप से 'SaveUserSignup' को' SaveUserSignupAsync' 'नाम देने पर लागू होंगे। –

1

आपकी समस्या यह है कि आप तुल्यकालिक और async कोड मिश्रण कर रहे हैं। यह किया जा सकता है, लेकिन मुश्किल है। आपका सबसे अच्छा शर्त है कि आप अपने http हैंडलर एसिंक को भी बनाएं:

public class VisitorSignupHandler : HttpTaskAsyncHandler 
    { 
     public override async Task ProcessRequestAsync(HttpContext context) 
     { 
      //Get the user's name and email address 
      var UserFullName = context.Request.QueryString["name"].UrlDecode(); 
      var UserEmailAddress = context.Request.QueryString["email"].UrlDecode(); 

      //Save the user's information 
      await UserSignup.SaveUserSignup(UserFullName, UserEmailAddress); 
.. 

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