通常,並行處理僅與CPU密集型操作相關。但是,PLINQ使用WithDegreeOfParallelism擴展特別提供IO密集型支持。例如:用於錯誤處理的並行I/O和重試邏輯
from site in new[]
{
"www.albahari.com",
"www.linqpad.net",
"www.oreilly.com",
"www.takeonit.com",
"stackoverflow.com",
"www.rebeccarey.com"
}
.AsParallel().WithDegreeOfParallelism(6)
let p = new Ping().Send (site)
select new
{
site,
Result = p.Status,
Time = p.RoundtripTime
}
但如果supporting IO is the goal of WithDegreeOfParallelism,怎能PLINQ進一步擴展或用於實現一個「重試」的效果,這是典型的IO操作?那麼「延遲」效應呢?
例如,如果IO通過WCF服務調用引發CommunicationException,我可能會希望再次使用「3次嘗試」策略進行相同的請求,然後再轉到下一個資源。我可能還需要在每次嘗試之間等待一分鐘。當我在每次嘗試之間「等待」一分鐘時,我不希望線程阻塞等待。
在這MSDN article作者開始與我上面顯示的類似的查詢。然後他轉換查詢,以便不阻塞任何線程。不幸的是,他在這個過程中失去了WithDegreeOfParallelism。無論如何,當發生錯誤時,他沒有解決「重試」問題。
任何人都知道或者知道如何做到這一點?
我正在考慮製作一個特殊的IEnumerable包裝器,允許在PLINQ正在收集集合時重新插入值。這確實會導致「重試」行爲,但它仍然不允許「重試之間1分鐘的延遲」要求。我可以使用Thread.Sleep()創建1分鐘的延遲,但我試圖不阻塞線程。
想法?
是的,文章的最後一個例子確實展示瞭如何擁有非阻塞線程,但是它忽略了WithDegreeOfParallism(),這意味着它可能會導致數百個IO調用,實際上我可能只需要5個未完成的IO請求。另外,IO的PLINQ可能是反模式,但它們通過提供WithDegreeOfParallelism()擴展來鼓勵反模式。我編輯了我的問題;請參閱我提供的鏈接,解釋WithDegreeOfParallelism是爲阻止IO而設計的。 –
@Brent不要忘記PLINQ是在異步等待之前設計的。 – svick
@BrentArias,這可能對客戶端應用程序可行,但對於服務器端應用程序+5每個請求更多的線程可能很容易殺死可伸縮性。你寫*「我可以使用Thread.Sleep()創建1分鐘的延遲,但是我試圖不阻塞線程。」*那麼爲什麼要用同步IO調用阻塞它們,而你可以使用'async/await' ?這並沒有太大的不同。 – Noseratio