2017-03-02 103 views
5

我知道您應該只對非「CPU密集型」的東西使用異步,例如,文件寫入,網絡電話等,因此我也知道把每種方法都包裝進Task.Run或類似的東西是沒有意義的。將非異步方法(可以進行Web調用)封裝到異步中

但是我應該怎麼做,當我知道一個方法進行網絡調用,但它不提供異步接口。在這種情況下值得包裝嗎?

具體的例子:

我在我的WebAPI的應用程序(服務器)使用CSOM(客戶端SharePoint對象模型),並希望得到一個SharePoint列表。

這通常是做過這樣的:

[HttpGet] 
[Route("foo/{webUrl}")] 
public int GetNumberOfLists(string webUrl) 
{ 
    using (ClientContext context = new ClientContext(webUrl)) 
    { 
     Web web = context.Web; 
     context.Load(web.Lists); 
     context.ExecuteQuery(); 

     return web.Lists.Count; 
    } 
} 

而且我認爲它更改爲這樣的事情:

[HttpGet] 
[Route("foo/{webUrl}")] 
public async Task<int> GetNumberOfLists(string webUrl) 
{ 
    using (ClientContext context = new ClientContext(webUrl)) 
    { 
     Web web = context.Web; 
     context.Load(web.Lists); 
     await Task.Run(() => clientContext.ExecuteQuery()); 

     return web.Lists.Count; 
    } 
} 

是否有意義和幫助?據我瞭解,我只是創建/需要一個新的線程來執行查詢(「開銷」),但至少請求線程將自由/準備好另一個請求(這很好)。

但這是否值得,應該這樣做?

如果是這樣的話: 微軟不提供「異步」方法或者他們不關心它是不是很奇怪?

編輯: 更新爲使用Task.Run如在評論中所建議的。

+0

不要使用'Task.Factory.StartNew',使用'Task.Run'。至於調用* *的SharePoint,上下文有'ExecuteQueryAsync'方法,它可以適用於返回任務 –

+0

我沒有在我使用我的CSOM庫'ExecuteQueryAsync' ....其他的事情我改變。 –

+0

剛剛通過nuget上傳到'Microsoft.SharePointOnline.CSOM,16.1.6216' - 仍然沒有'ExecuteQueryAsync'。 –

回答

3

但是我應該怎麼做當我知道一個方法進行網絡調用,但它不提供異步接口。

不幸的是仍然有點常見。隨着不同的圖書館更新他們的API,他們最終會趕上。

在這種情況下是否值得包裝它?

是的,如果你正在處理一個UI線程。否則,不。

具體的例子......在我的WebAPI的應用程序(服務器)

然後,不,你不希望在Task.Run包。正如我在article on async ASP.NET中提到的:

您可以通過等待Task.Run開始一些後臺工作,但這樣做沒有意義。事實上,這實際上會干擾ASP.NET線程池啓發式技術,從而影響您的可伸縮性。作爲一般規則,不要將工作排隊到ASP.NET上的線程池。

包裝與Task.Run在ASP.NET:

  • 與ASP.NET線程池的啓發式干擾兩次(通過採取線程現在再後來釋放它)。
  • 增加開銷(代碼必須切換線程)。
  • 不騰出一個線程(用於此請求的線程總數幾乎等於只是調用同步版本)。

據我瞭解,我只是創建/需要一個新的線程來執行查詢(「開銷」),但至少請求的線程將免費/準備好另一個請求(這將是很好的) 。

是的,但你所做的只是跳線,沒有任何好處。用於阻止查詢結果的線程是ASP.NET必須用來處理請求的線程之一,因此通過消耗另一個線程來釋放一個線程並不是一個好的折衷。

微軟不提供開箱即用的「異步」方法或者他們不關心它是不是很奇怪?

一些「舊」MS API尚未添加到async版本。他們肯定應該,但開發人員時間是一個有限的資源。

+0

完美的答案,正是我「尋找」 - 謝謝你! –

0

這是我個人對您的問題的看法,對我而言,上述方式並非必需。當我們在IIS中託管您的API時,服務器會從它在服務器中的線程池中分配一個線程。 IIS還具有maxConcurrentRequestsPerCPU maxConcurrentThreadsPerCPU的設置。您可以設置這些值來服務請求,而不是自己處理請求。