2013-07-25 26 views
7

Tôi bị kẹt trong một bế tắc không đồng bộ và tôi không thể tìm ra cú pháp chính xác để sửa nó. Tôi đã xem xét một số giải pháp khác nhau, nhưng dường như không thể tìm ra nguyên nhân gây ra vấn đề.Async Await Handler Deadlock

Tôi đang sử dụng Parse làm phụ trợ và cố gắng sử dụng trình xử lý để ghi vào bảng. xử lý của tôi trông giống như sau:

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; } } 
} 

Sau đó, nó được gọi tầng giữa của tôi:

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(); 
    } 
} 

Mặc dù điều này dường như được bị mắc kẹt tại Wait(). Tôi đã có ấn tượng rằng Wait() sẽ chỉ đơn giản là chờ cho công việc hoàn thành, sau đó trở lại hoạt động bình thường. Điều này có đúng không?

Trả lời

13

Bạn đang gặp phải sự cố bế tắc chung mà tôi mô tả on my blogin a recent MSDN article.

Tóm lại, await theo mặc định sẽ tiếp tục phương thức async bên trong ngữ cảnh "được chụp" và trên ASP.NET, chỉ một chuỗi được phép vào "ngữ cảnh" đó tại một thời điểm. Vì vậy, khi bạn gọi Wait, bạn đang chặn một chuỗi bên trong ngữ cảnh đó và await không thể nhập ngữ cảnh đó khi nó sẵn sàng tiếp tục phương thức async. Vì vậy, các chủ đề trong bối cảnh bị chặn tại Wait (chờ đợi cho các phương pháp async để hoàn thành), và phương pháp async bị chặn chờ đợi bối cảnh được miễn phí ... bế tắc.

Để khắc phục điều này, bạn nên "không đồng bộ tất cả các cách". Trong trường hợp này, sử dụng HttpTaskAsyncHandler thay vì IHttpHandler:

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

Cảm ơn bạn! Tôi đọc blog của bạn trước khi đăng bài này và không thể tìm ra cú pháp. Điều này làm việc tuyệt vời. Cảm kích điều đó. –

+1

Bạn được chào đón! P.S. Cung cấp cho [tài liệu TAP] (http://msdn.microsoft.com/en-us/library/hh873175.aspx) đọc tốt; có một số quy ước 'async' sẽ áp dụng ở đây, đặc biệt là đổi tên 'SaveUserSignup' thành' SaveUserSignupAsync'. –

1

Vấn đề của bạn là bạn đang trộn đang đồng bộ và async. Điều này có thể được thực hiện, nhưng là khó khăn. Đặt cược tốt nhất của bạn là làm cho trình xử lý http của bạn không đồng bộ:

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); 
.. 

     } 
    } 
Các vấn đề liên quan