2012-08-09 101 views
11

我需要內防止死鎖不使用的await調用異步方法時

public override void OnActionExecuting(ActionExecutingContext filterContext) 

從調用返回一個Task的方法它不會讓我做這個方法異步它拋出以下

異步模塊或處理程序在異步操作仍未完成時完成。

,並呼籲

entityStorage.GetCurrentUser().Result 

當我得到一個僵局。我怎樣才能避免這種情況?

我一直在玩弄它的到來了東西一樣

entityStorage.GetCurrentUser().Result.ConfigureAwait(false).GetAwaiter().GetResult(); 

但是,這是行不通的。我該怎麼做?我的解決方案需要使用ASP.NET 4和Async Targetting Pack,我不能在部署到Azure時使用ASP.NET 4.5。

+0

在這裏找到了答案http://stackoverflow.com/a/5097066/168012如果有人有更好的解決方案,請分享 – Tom 2012-08-09 16:56:50

+2

您是從'AsyncController'而不是'Controller'派生的嗎? – 2012-08-10 00:53:27

+0

請[在此投票](https://aspnet.codeplex.com/workitem/9582)爲MVC團隊添加對「異步」動作過濾器的支持。 – 2013-06-11 14:21:19

回答

2

由於await只是語法糖,因此編譯器會爲您重寫一個延續,最直接的途徑就是採取任何代碼來遵循您的等待並使其成爲ContinueWith調用。

所以,像這樣:

entityStorage.GetCurrentUser().ContinueWith(t => 
{ 
    // do your other stuff here 
}); 
12

造成死鎖的原因是explained here。總之,不要阻止async的代碼。您應該在您的庫中使用ConfigureAwait(false)async代碼和await結果(不使用ResultWait)。

更新:請求vote here爲MVC團隊添加支持async動作過濾器。

+0

我很難找到這樣說的鏈接/頁面,但我曾經有人告訴過我,如果提供一個鏈接(尤其是一個外部的鏈接),您應該將關鍵位複製到SO回答。這裏有點提到,FWIW:http://meta.stackexchange.com/questions/118582/what-is-an-acceptable-answer – 2012-08-09 17:55:31

+0

你是對的;您所指的元問題最近被刪除,作爲「讓我們成爲更好的地方」戰略的一部分。然而,正如Jon Skeet評論的那樣:如果我知道答案並且只有時間發佈鏈接,那麼總比沒有好。 – 2012-08-10 00:10:28

+0

我遇到的問題是,如果我嘗試使用async關鍵字並使方法異步,則該方法拋出「異步操作尚未完成時異步模塊或處理程序已完成」。 – Tom 2012-08-16 14:00:17

1

如果MUST轉換非同步進行同步。

public User GetCurrentUserSynch() 
    { 
     return Task.Run(() => 
     { 
      var asyncResult = entityStorage.GetCurrentUser(); 
      while (!asyncResult.IsCompleted) 
      { 
       Application.Current.TryFindResource(new object()); // This is for WPF but you can do some other nonsense action of your choosing 
      } 

      return asyncResult.Result; 
     }).Result; 
    } 

否則請使用@ Stephen的回答。