簡體   English   中英

如何在Thread-Local狀態下使用Parallel.ForEach?

[英]How to use Parallel.ForEach with Thread-Local state?

問題:我在一篇文章中看到了兩個帶有WebCLientParallel.Foreach()下載URL的WebCLient 作者建議在第一個例子中,如果我們有一個100個網址的數組 - 將啟動100個WebClient,其中大多數將超時。 所以他提出了第二個實現,他使用了線程局部狀態,他說“ 我們需要生成盡可能多的WebClient()對象 ”。

問題:第二個示例如何確保不會發生超時? 或者換句話說,第二個例子如何考慮連接的局部限制? 客戶會被重復使用嗎?

資源:

// First example
Parallel.ForEach(urls,
    (url,loopstate,index) =>
    {
        WebClient webclient = new WebClient();
        webclient.DownloadFile(url, filenames[index];
    });

// Second example
Parallel.ForEach(urls,
    () => new WebClient(),
    (url, loopstate, index, webclient) =>
       {
           webclient.DownloadFile(url, filenames[index]);
    },
    (webclient) => { });

注意:在多個線程上生成WebClient僅用於演示目的。 我知道使用異步操作會更有效。

我得到源代碼的鏈接 (我簡化了一點): 我什么時候應該使用Parallel.ForEach? 我什么時候應該使用PLINQ? 查看“線程本地狀態”一章。

換句話說,第二個例子如何考慮連接的本地限制? 客戶會被重復使用嗎?

第二個例子的作用是,不是每次迭代創建一個WebClient對象,而是每個線程創建一個WebClient 這意味着如果Parallel.ForEach使用4個線程,它將創建4個實例,並將在迭代之間重用這些對象。 因此,能夠重新使用由每個客戶端創建的連接而不是新實例,而新實例又必須等待所有其他客戶端連接關閉。

最終,所有客戶端都在爭奪通過底層ServicePointManager.DefaultConnectionLimit可用的相同IO資源。 您打開的連接越少,每個請求完成執行的時間就越多。 這也可以通過增加允許的連接限制數來解決,默認為2。

一般來說,不需要使用多個線程來執行並發IO請求。 並行性實際上並沒有幫助。

通過使用線程局部狀態,我們現在每個線程有一個WebClient。 每次迭代不是一個客戶端。

作者的想法是,我們現在有更少的WebClient浮動並消耗資源。 這個論點是假的,因為目前沒有執行任何調用的WebClient實例不會占用任何資源。 Dispose對WebClient沒有任何作用。 包裹它使用,你就完成了。

需要在這里使用PLINQ,因為Parallel很容易產生無限數量的線程。 使用IO,您需要自己控制DOP。 只有使用PLINQ才能設置精確的DOP。 TPL無法知道您的網絡可以支持多少並發請求。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM