2013-12-09 38 views
4

我有很多Utils類,我用於許多不同的項目,其中大多數是靜態的,通常甚至不會互相調用。我的意圖是利用新的異步/等待功能,但不重寫所有的東西,所以我的問題是:我可以添加一個新的方法爲每個現有的方法命名MethodAsync與Task.Run((()=>方法名)?用異步/等待重寫我的Utils庫的正確方法

例如:

//old code that will not be removed 
static void DoSomething() 
{ ... } 

//new code that will be added 
static async Task DoSomethingAsync() 
{ 
    //not really sure if Im supposed to use await/async here. 
    //isn't Task awaitable even without async?? 
    return await Task.Run(() => DoSomething()); 
} 

基本上在舊的代碼,我只是有一個正常的同步方法,而在新的一個我有可能即使在另一個線程運行的異步方法,如果CLR把它看成一個CPU綁定方法。

如果我正確理解,每個異步方法都按定義包含一個等待對象,它是一個Task或另一個異步方法。

這意味着,只要我可以使用異步.NET方法,我應該等待它,並將我的調用方法標記爲異步。

但是,其他任何不調用任何異步方法但需要一些時間才能完成的方法應該使用Task.Run調用進行調用。

對不對?

編輯

,所以我已閱讀全部張貼鏈接,MSDN上的最佳實踐和一些博客文章,但我仍然需要一個完整的程序來遵循新的異步編碼時/等待功能。 這是我到目前爲止:

1)具有異步替代的每個.NET方法應該使用異步替代。 (據我所知,.NET異步方法已經存在,只適用於可以異步的方法)。 2)每個使用異步方法的方法也應該做成異步。 3)每個不使用異步方法的方法(因爲沒有可用的)但仍需要一些cpu時間來執行應該通過使用Task.Run包裝它們來實現異步(我知道在這種情況下它應該是使用Task.Run的客戶端,如果他們想要的話,但因爲我只爲那些需要超過50ms執行的方法添加這些包裝器,並且仍然可以使用該方法的非異步版本,所以我仍然不明白爲什麼我不應該把這個包裝放入庫中)。

4)每一個需要非cpu-time的方法都會導致它等待其他資源(如internet,數據庫,事件等等)應該使用TaskFactory.FromAsync或TaskCompletionSource。

5)現在不推薦使用System.Threading.Tasks.Parallel.Invoke(method1,method2等)。從我讀的Task.Run已經運行併發線程,如果CLR認爲需要併發。所以看起來Task.Run已經在需要的時候使用了Parallel.Invoke。

+11

不要那樣做。除非它們實際上是異步的,否則不要創建'* Async()'方法;永遠不要在庫中調用Task.Run()。 http://msdn.microsoft.com/en-us/magazine/jj991977.aspx – SLaks

+1

[我應該公開同步方法的異步包裝?](http://blogs.msdn.com/b/pfxteam/archive/2012/ 04/13/10293638.aspx) – ken2k

+0

它說'Parallel.Invoke'已被棄用?它在哪裏聲明'Task.Run'使用'Parallel.Invoke'?我認爲它導致了'ThreadPool'的使用。 – Lukazoid

回答

6

我終於能找到清除我所有的疑慮良好的資源:

第一個是「基於任務的異步模式」可在http://www.microsoft.com/en-us/download/details.aspx?id=19957 本文檔介紹了異步/ AWAIT功能,如何/時使用它,它包含了很多實際的例子和一些非常有用的靜態方法,我現在正在每個項目中使用!

第二個是「異步的禪:爲最佳性能的最佳做法」,可http://channel9.msdn.com/Events/BUILD/BUILD2011/TOOL-829T 這是異步功能的完整概述,與並行功能的一些報道,同時也解釋了爲什麼它永遠也不應該使用Task.Run()方法的庫,但它應該是消費者選擇。

所以最後我真的很困惑多線程與異步代碼,我無法領會異步代碼的優點,因爲我只是在看當時的單一方法,而異步代碼的真正好處只能看到如果整個項目(或至少它的一致部分)是按照異步模式編寫的。 例如在asp.net中,如果沒有任何阻塞代碼(一切都以異步方式編寫),那麼當你的一個線程正在等待一個異步操作時,一個線程可以服務另一個客戶端,從而提高可伸縮性,而在一個xaml應用程序中啓動異步操作的線程可以立即返回到支持您的UI,而不是等待該操作結束,從而提高響應速度。

+0

+1爲了做一些真正的發現,我喜歡談論「異步的禪宗」。當你在等待一些外部資源時,async/await的真正優點就來了,例如文件系統,數據庫,一些網絡流量,系統互斥等。另請參閱[本答案](http://stackoverflow.com/a/18015586/921321)以獲取何時使用'Task.Run' – Lukazoid

5

這在Should I expose asynchronous wrappers for synchronous methods?討論這篇文章,我想強調的部分,爲什麼這是不好的設計爲低於:

舉個例子,像Dictionary<TKey,TValue>.Add(TKey,TValue)的簡單方法。這是一個非常快速的方法,對吧?通常,是的,但請記住字典是如何工作的:它需要對密鑰進行散列才能找到合適的存儲區,並且需要檢查密鑰與存儲區中已有的其他條目是否相等。那些哈希和平等檢查可以導致對用戶代碼的調用,誰知道這些操作做了什麼或者他們需要多長時間。字典上的每個方法是否應該公開一個異步封裝器?這顯然是一個極端的例子,但也有更簡單的例子,比如Regex。提供給Regex的正則表達式模式的複雜性以及輸入字符串的性質和大小可以對與Regex匹配的運行時間產生重大影響,以至於Regex現在支持可選的超時...應該使用Regex上的每種方法都有一個異步等價物?我真的希望不會。

很顯然,我建議你閱讀整篇文章太多,但我希望上面的亮點有很大原因暴露*Async()方法在一個庫中不應該換行同步的。

我希望這會有所幫助。