2016-01-27 64 views
5

我正在使用System.Net.Http.HttpClient進行HTTP調用。看來所有的調用都必須是異步的。使用HttpClient時避免從異步函數返回類型任務<Object>

比方說,我有以下的項目結構: MVC Web應用程序 - >業務層 - >數據層

數據層我正在HTTP調用一個Web API返回的數據和我結束使用了這樣的功能:

public async Task<IList<Product>> GetProducts() 
{ 
    HttpResponseMessage response = await client.GetAsync("api/products"); 
    string data = await response.Content.ReadAsStringAsync(); 
    IList<Product> products = JsonConvert.DeserializeObject<IList<Product>>(data); 

    return products; 
} 

這再經過到BusinessLayer:

public Task<IList<Product>> GetProducts(string name = null) 
{ 
    return _repository.GetProducts(name); 
} 

然後終於在MVC控制器:

public IActionResult Index() 
{ 
    Task<IList<Product>> ProductsTask = _manager.GetProducts(); 

    IList<Product> ProductsNonTask = products.Result.ToList(); 

    return View(); 
} 

難道我真的讓每一個函數返回一個類型爲Task<IList<Product>>,爲我的MVC控制器的列表?正如你可以在MVC控制器中看到的,我必須首先檢索產品,並在其周圍包裝任務。當我通過它查看產品列表時,調試器看起來有些奇怪。那麼你可以看到我將它們轉換爲常規產品列表。

我想知道是否正確的做法是讓我的所有函數都返回類型Task<IList<Product>>一直到我的MVC控制器,或者如果有一個解決方法,以便我的函數仍然可以返回標準列表產品,但繼續使用HttpClient的異步功能?

UPDATE:這有什麼錯與執行以下操作:

public IList<Product> GetProducts() 
{ 
    Task<HttpResponseMessage> response = client.GetAsync("api/products"); 
    if (response.Result.IsSuccessStatusCode) 
    { 
      string data = response.Result.Content.ReadAsStringAsync().Result; 
      IList<Product> products = JsonConvert.DeserializeObject<IList<Product>>(data); 

      retVal = products; 
    } 
} 
+0

'執行以下操作有什麼不妥:'是的,代碼不能編譯(出於各種原因)。你可以通過簡單地編譯它來解決這個問題。 – Servy

+0

我很抱歉,由於我複製並粘貼和更改,我無意中將await關鍵字留在了此處。現在已經修復了。 –

+0

由於許多不同的原因,代碼仍然不會編譯。 – Servy

回答

7

如果你想操作實際上是異步的,它需要是異步的一路上漲。

您在Task上屏蔽的時間爲WaitResult它不再是異步的。

所以,沒有。要麼一路使用異步,要麼完全不使用異步。

我想知道...如果有一個解決方法,以便我的函數仍然可以返回一個標準的產品列表,但繼續使用HttpClient的異步功能?

不,沒有。

您應該只是讓您的代碼異步,因爲它具有可伸縮性和性能方面的許多優點。但如果您反對這樣做,您可以使用具有同步Web操作的WebClient

+0

如果是這種情況,我正試圖找到一種方法來仍然使用HttpClient的異步方法,而無需爲我的函數返回類型Task。例如,我認爲我可以這樣做:Task response = client.GetAsync(「api/customers」);然後我的函數本身不必返回類型Task,因爲我正在取消await關鍵字。 –

+1

@BlakeRivell不要。既可以使用異步,也可以完全避免使用異步。不要試圖混合,因爲這隻會讓你陷入困境。 – i3arnon

+0

@BlakeRivell更多這裏:http://blogs.msdn.com/b/pfxteam/archive/2012/04/13/10293638.aspx – i3arnon

1

難道我真的不得不讓每一個函數返回一個類型的任務>引導到我的MVC控制器的列表嗎?

是的,你必須和你甚至沒有抓住所有的地方,因爲Index本身也必須是異步的。

異步真的有傳染性。必要時使用,而不是默認使用。

+0

因爲我使用HttpClient,我必須在他的情況下使用它嗎? –

+0

HttpClient強制異步IO(不幸),但是如果這對你來說足夠好,你可以阻止它。這可以讓你免於「感染」。看到這個決定:http://stackoverflow.com/a/25087273/122718爲什麼EF 6教程使用異步調用? http://stackoverflow.com/a/12796711/122718我們應該默認切換到使用異步I/O嗎? – usr

+0

阻止HttpClient返回的任務永遠不會死鎖,順便說一句。這是安全的,因爲HttpClient不使用可能安裝的同步上下文。 – usr

相關問題