2013-10-30 20 views
2

我有以下作用掛着,再也沒有回來:異步MVC

public Task<ActionResult> ManageProfile(ManageProfileMessageId? message) 
     { 
      ViewBag.StatusMessage = 
       message == ManageProfileMessageId.ChangeProfileSuccess 
        ? "Your profile has been updated." 
           : message == ManageProfileMessageId.Error 
             ? "An error has occurred." 
             : ""; 
      ViewBag.ReturnUrl = Url.Action("ManageProfile"); 

      var user = UserManager.FindByIdAsync(User.Identity.GetUserId()); 
      var profileModel = new UserProfileViewModel 
      { 
       Email = user.Email, 
       City = user.City, 
       Country = user.Country 
      }; 

      return View(profileModel); 
     } 

但是當我把它轉換成這樣:

public async Task<ActionResult> ManageProfile(ManageProfileMessageId? message) 
     { 
      ViewBag.StatusMessage = 
       message == ManageProfileMessageId.ChangeProfileSuccess 
        ? "Your profile has been updated." 
           : message == ManageProfileMessageId.Error 
             ? "An error has occurred." 
             : ""; 
      ViewBag.ReturnUrl = Url.Action("ManageProfile"); 

      var user = await UserManager.FindByIdAsync(User.Identity.GetUserId()); 
      var profileModel = new UserProfileViewModel 
      { 
       Email = user.Email, 
       City = user.City, 
       Country = user.Country 
      }; 

      return View(profileModel); 
     } 

它返回的時候了。所以我不知道這是怎麼回事?如果它的返回沒有等待FindByIdAsync的結果那麼簡單,那麼爲什麼我沒有看到沒有任何內容的視圖。

所以,在我看來,它沒有等待的回報:

UserManager.FindByIdAsync(User.Identity.GetUserId()); 

也不返回空個人資料,也引發了異常。所以,當它掛在第一個例子中時,我不知道這裏發生了什麼。

+2

你的第一個代碼片段不能編譯。 –

+0

在你的第二個代碼片段中沒有錯誤,這個問題很可能與我們沒有代碼的'UserManager.FindByIdAsync'方法有關。如果我猜測我會說它沒有啓動它返回的任務,所以這個任務將無限期地等待。作爲慣例,異步方法應始終啓動它返回的任務。 –

回答

9

我假設你的第一個例子是使用Result,因此causing a deadlock that I explain on my blog

總之,ASP.NET提供了一個「請求上下文」,它一次只允許一個線程。當您使用Result阻塞線程時,該線程被鎖定到該上下文中。稍後,當FindByIdAsync嘗試在該上下文中恢復時,它不會因爲其中有另一個線程已被阻止。

+0

感謝您的博客文章。正是我需要的。 –