Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何将Parallel.ForEach与线程本地状态一起使用?_C#_Multithreading_Parallel Processing_Thread Local Storage - Fatal编程技术网

C# 如何将Parallel.ForEach与线程本地状态一起使用?

C# 如何将Parallel.ForEach与线程本地状态一起使用?,c#,multithreading,parallel-processing,thread-local-storage,C#,Multithreading,Parallel Processing,Thread Local Storage,问题:我在一篇文章中看到了一个Parallel.Foreach()的两个实现使用WebCLient下载URL。作者建议,在第一个示例中,如果我们有一个100个URL的数组,那么将启动100个WebClient,其中大多数将超时。因此,他提出了第二个实现,其中他使用了线程本地状态,并表示“将根据需要生成尽可能多的WebClient()对象” 问题:第二个示例如何确保不会发生超时?或者换句话说,第二个示例如何考虑连接的局部限制?客户端会被重用吗 来源: 注意:在多个线程上生成WebClient仅用

问题:我在一篇文章中看到了一个
Parallel.Foreach()的两个实现
使用
WebCLient
下载URL。作者建议,在第一个示例中,如果我们有一个100个URL的数组,那么将启动100个WebClient,其中大多数将超时。因此,他提出了第二个实现,其中他使用了线程本地状态,并表示“将根据需要生成尽可能多的WebClient()对象”

问题:第二个示例如何确保不会发生超时?或者换句话说,第二个示例如何考虑连接的局部限制?客户端会被重用吗

来源:

注意:在多个线程上生成WebClient仅用于演示目的。我知道异步操作会更有效

链接我从中获得源代码(我简化了一点):看看“线程本地状态”一章

换句话说,第二个例子如何考虑 本地连接限制?客户端会被重用吗

第二个示例所做的是,它不是在每次迭代中创建
WebClient
对象,而是在每个线程中创建
WebClient
。这意味着如果
Parallel.ForEach
使用4个线程,它将创建4个实例,并在迭代之间重用这些对象。因此,能够重新使用每个客户端创建的连接,而不是新实例,而新实例又必须等待所有其他客户端连接关闭

最终,所有客户端都在争夺通过底层
ServicePointManager.DefaultConnectionLimit
提供的相同IO资源。打开的连接越少,完成每个请求的时间就越多。这也可以通过增加允许的连接限制数量(默认为2)来解决


一般来说,不需要使用多个线程来执行并发IO请求。并行性在这里实际上没有帮助。

通过使用线程本地状态,我们现在每个线程有一个WebClient。每次迭代都没有一个客户机

作者的想法是,我们现在有更少的网络客户端的浮动和消耗资源。这个论点是假的,因为目前没有执行任何调用的WebClient实例不会占用任何资源。Dispose在WebClient上不执行任何操作。用包装纸把它包起来,你就完成了


您需要在这里使用PLINQ,因为Parallel容易产生无限数量的线程。使用IO时,您需要自己控制DOP。只有使用PLINQ才能设置精确的DOP。TPL不知道您的网络可以支持多少并发请求。

但在第一种情况下,也会为每个请求创建
WebClient
。因此。。第二个示例如何限制并行连接的数量?因此,在第二个示例中,如果
parallel.Foreach()
启动更多操作系统能够处理的连接,它们也会超时,对吗?优化只是为了重用客户端,示例不会阻止超时?@f0rt-Yes。如果理论上
Parallel.ForEach
使用了100个线程,那么就有100个
WebClient
实例。据我所知,这两个实例都支持DOP:-PLINQ via WithDegreeOfParallelism()方法-Parallel.ForEach()via parallellel可枚举。WithDegreeOfParallelism唯一的区别是并行。ForEach()可以使用少于指定的数量。不管怎样,我明白你说的。谢谢。:)对。这意味着WithDegreeOfParallelism可能使用一个线程来驱动网络,这对性能来说是灾难性的。好吧,这个评论还不清楚。在单核计算机上,虽然指定了20,但可能会得到一个线程事件。
// 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) => { });