[英]Best practices to parallelize using async workflow
讓我們說我想刮一個網頁,並提取一些數據。 我最有可能寫這樣的東西:
let getAllHyperlinks(url:string) =
async { let req = WebRequest.Create(url)
let! rsp = req.GetResponseAsync()
use stream = rsp.GetResponseStream() // depends on rsp
use reader = new System.IO.StreamReader(stream) // depends on stream
let! data = reader.AsyncReadToEnd() // depends on reader
return extractAllUrls(data) } // depends on data
let!
告訴F#在另一個線程中執行代碼,然后將結果綁定到變量,並繼續處理。 上面的示例使用兩個let語句:一個用於獲取響應,一個用於讀取所有數據,因此它至少生成兩個線程(如果我錯了,請糾正我)。
雖然上面的工作流程會產生多個線程,但執行順序是串行的,因為工作流程中的每個項目都依賴於前一個項目。 在其他線程返回之前,無法在工作流程中進一步評估任何項目。
擁有多個let!
有任何好處let!
在上面的代碼?
如果沒有,這個代碼將如何改變以利用多個let!
聲明?
關鍵是我們不會產生任何新線程。 在整個工作流程中,ThreadPool消耗了1或0個活動線程。 (例外,直到第一個'!',代碼在執行Async.Run的用戶線程上運行。)“let!” 當Async操作在海上時,讓我們離開一個線程,然后在操作返回時從ThreadPool中獲取一個線程。 (性能)優勢是對ThreadPool的壓力較小(當然主要的用戶優勢是簡單的編程模型 - 比您編寫的所有BeginFoo / EndFoo /回調內容要好一百萬倍)。
我正在寫一個答案,但Brian打敗了我。 我完全同意他的觀點。
我想補充一點,如果你想並行化同步代碼,正確的工具是PLINQ,而不是異步工作流,就像Don Syme解釋的那樣 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.