2012-07-06 62 views
8

我使用Visual Studio 2012 RC與.Net 4.5和ASP MVC 4 RC。只要我使用異步,它就會掛起。控制器操作方法使用異步,但本身不是異步控制器方法。ASP.Net MVC 4控制器在使用異步時掛起

沒有錯誤記錄或拋出異常,但瀏覽器永遠顯示「等待www.myweb.local」。

// Simplest possible async 
public class Waiter 
{ 
    public async Task<int> GetValue() 
    { 
     await Task.Yield(); 
     return await Task.Factory.StartNew(() => 42); 
    } 
} 

// simplest possible controller that uses the async 
public class HomeController : Controller 

    public ActionResult Index() 
    { 
     var waiter = new Waiter(); 
     var resultTask = waiter.GetValue(); 
     int result = resultTask.Result; 

     // it never gets here 
     return View(); 
    } 
} 

我這樣做,是被指出in this answer的事情,它仍然無法正常工作。 即。該web.config包含

<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/> 

而魔術字await Task.Yield();是在異步方法。

.Net框架版本是4.5.50501。我在IIS Express和IIS 6.0上觀察到了這種行爲。

我嘗試運用「2012年7月更新」到VS2012,但沒有解決問題。

This answer suggests,這可能是因爲任務已經完成,當我等待它,但是如果是這樣的話,這應該工作,它不會:

public class Waiter 
{ 
    public async Task<int> GetValue() 
    { 
     await Task.Yield(); 
     return await Task.Factory.StartNew(() => 
      { 
       Thread.Sleep(1500); 
       return 42; 
      }); 
    } 
} 

一對夫婦的人都認爲, ConfigureAwait(false)是需要的,但是這個代碼不工作之一:

public async Task<int> GetValue() 
    { 
     var task = new Task<int>(() => 42); 
     return await task.ConfigureAwait(false); 
    } 

以下確實工作與Razor視圖引擎,但與火花。當然,應該有辦法讓另一個場景也可以工作?可以不使用同步代碼中的異步任務嗎?

public class Waiter 
{ 
    public async Task<int> GetValue() 
    { 
     return await Task.Factory.StartNew(() => 42); 
    } 
} 

public class HomeController : Controller 
{ 
    public async Task<ActionResult> IndexAsync() 
    { 
     await Task.Yield(); 
     var waiter = new Waiter(); 
     int result = await waiter.GetValue(); 

     return View(); 
    } 
} 

我知道,這是不會被釋放的軟件,但微軟的駐地協調員通常是相當穩定的,所以我很驚訝,它失敗,並在無益的方式失敗。

+2

很抱歉,如果我失去了一些東西,但爲什麼必須通過訪問結果屬性,而不是將其標記爲異步和使用的await有索引塊?如果這是有意的,您可能需要使用ConfigureAwait(假),這樣的延續不回安排在同一個線程。 – 2012-07-06 15:12:27

+0

我測試移植現有網站.NET 4.5。它使用火花視圖引擎。我想在處理異步控制器之前獲得異步工作,以及Spark是否可以處理Task 或不(我的初始印象是否)。但不管我是否可以這樣做,這種情況都應該起作用。 – Anthony 2012-07-06 15:23:17

+0

你爲什麼從AsyncController派生?這沒有必要。見我的異步樣品http://www.asp.net/mvc/tutorials/mvc-4/using-asynchronous-methods-in-aspnet-mvc-4 – RickAndMSFT 2012-07-07 20:15:18

回答

1

我有異步的beta就好了工作。我沒有測試過,但我猜這是因爲你的控制器方法不是異步的。將其更改爲:

public async Task<ActionResult> IndexAsync() 
{ 
    var waiter = new Waiter(); 
    int result = await waiter.GetValue(); 

    // it never gets here 
    return View(); 
} 
+0

如果它「因爲控制器方法不是異步」你是說,使用異步任務將同步代碼不會起作用?否則,應該有辦法讓這個代碼工作。 – Anthony 2012-07-06 15:51:12

+0

OK,編輯追加任務,而我是消化... – 2012-07-06 15:51:18

+0

那麼的GetValue(),則沒有完成......我無法從你有什麼想一個明顯的原因我的頭了這一關頂我現在在火車上!如果沒有人毆打我,我會再看看。 – 2012-07-06 15:57:00

9

您正在導致死鎖,just like this question

詹姆斯·曼寧的建議是正確的,但你必須awaitConfigureAwait的結果,就像這樣:

public async Task<int> GetValue() 
{ 
    var task = new Task<int> (() => 42); 
    return await task.ConfigureAwait(false); 
} 

一般來說,混合式同步和異步代碼是一個非常糟糕的主意,除非你真的知道你」重新做。使控制器動作異步會好得多。

+1

我同意 - 特別是現在很容易使控制器方法異步。儘管我可以看到一些(非常非常罕見)的情況,在同步處理程序中並行運行一些任務是有意義的。總是值得這篇文章與異步控制器在你進入之前也讀:http://blog.stevensanderson.com/2010/01/25/measuring-the-performance-of-asynchronous-controllers/ – 2012-07-06 21:18:55

+0

當然任何C#程序使用async關鍵字「混合同步和異步代碼」?使用異步控制器意味着邊界位於框架中。 – Anthony 2012-07-06 22:31:52

+0

關於「它是如此容易,現在使控制器方法異步」 - 不,如果你有很多的使用火花視圖引擎現有的觀點。 – Anthony 2012-07-06 22:44:01

相關問題