如何指定的Parallel.ForEach执行的并行任务的数量? [英] How to specify the number of parallel tasks executed in Parallel.ForEach?

查看:902
本文介绍了如何指定的Parallel.ForEach执行的并行任务的数量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有〜500的任务,他们每个人的花费约5 seconds其中大部分时间是在等待远程资源的答复浪费。我想定义应催生了我自己(在一些测试)的线程数和运行这些线程的任务。当一个任务完成后,我想产卵,成为可用的线程上执行其他任务。

我发现 System.Threading.Tasks 最容易达到我想要的,但我认为这是不可能的指定应并行执行的任务数量。对于我的机器,它总是围绕8(四核CPU)。是否有可能以某种方式告诉多少任务应该并行地执行?如果不是这将是实现我想要的最简单的方法? (我试图与线程,但code是复杂得多)。我试图增加 MaxDegreeOfParallelism 参数,但只限制了最大数量,因此在这里没有运气...

这是在code,我有当前:

 使用系统;
使用System.Collections.Generic;
使用System.Linq的;
使用System.Text;
使用System.Threading.Tasks;

命名空间ConsoleApplication1
{
    类节目
    {
        私有静态列表<字符串> _list =新的名单,其中,串>();
        私有静态诠释_toProcess = 0;

        静态无效的主要(字串[] args)
        {
            的for(int i = 0; I< 1000; ++ I)
            {
                _list.Add(参数+ I);
            }

            变种W =新员工();
            VAR W2 =新StringAnalyzer();

            Parallel.ForEach(_list,新ParallelOptions(){MaxDegreeOfParallelism = 32},项=>
            {
                ++ _麦克罗公司一直供应;
                字符串数据= w.DoWork(项目);
                w2.AnalyzeProcessedString(数据);
            });

            Console.WriteLine(完成);
            Console.ReadKey();
        }

        静态无效完成(任务<字符串> T)
        {
            Console.WriteLine(t.Result);
            --_麦克罗公司一直供应;
        }
    }

    班工人
    {
        公共字符串的DoWork(串杆)
        {
            //这是一个长期运行的,但不是CPU任务繁重(下载东西来自互联网)
            System.Threading.Thread.Sleep(5000);
            回归面值+加工;
        }
    }

    类StringAnalyzer
    {
        公共无效AnalyzeProcessedString(字符串数据)
        {
            //比较短,没有CPU重
            System.Threading.Thread.Sleep(1000);
            Console.WriteLine(数据+和分析);
        }
    }
}
 

解决方案

由于LB提到,.NET Framework有执行I / O操作(请求数据库,Web服务等)的using IOCP内部,他们可以通过他们的名字承认 - 它的异步的结束按照约定。所以,你可以只使用它们来构建强大的可扩展的应用程序,可以同时处理多个请求。

修改:我已经完全改写了现代最佳实践的code的例子,使其成为更具可读性,更短的和易于使用的

对于.NET 4.5,我们可以使用方式:

 类节目
{
    静态无效的主要(字串[] args)
    {
        变种任务= Worker.DoWorkAsync();
        task.Wait(); //停止,等到我们的异步方法完成

        的foreach(在task.Result VAR项)
        {
            Console.WriteLine(项目);
        }

        到Console.ReadLine();
    }
}

静态类工人
{
    公共异步静态任务< IEnumerable的<字符串>> DoWorkAsync()
    {
        名单<字符串>结果=新名单,其中,串>();

        的for(int i = 0;我小于10;我++)
        {
            VAR请求=(HttpWebRequest的)WebRequest.Create(http://microsoft.com);
            使用(VAR响应=等待request.GetResponseAsync())
            {
                results.Add(response.ContentType);
            }
        }

        返回结果;
    }
}
 

在这里 是不错的MSDN教程的异步编程使用异步计谋。

I have ~500 tasks, each of them takes ~5 seconds where most of the time is wasted on waiting for the remote resource to reply. I would like to define the number of threads that should be spawned myself (after some testing) and run the tasks on those threads. When one task finishes I would like to spawn another task on the thread that became available.

I found System.Threading.Tasks the easiest to achieve what I want, but I think it is impossible to specify the number of tasks that should be executed in parallel. For my machine it's always around 8 (quad core cpu). Is it possible to somehow tell how many tasks should be executed in parallel? If not what would be the easiest way to achieve what I want? (I tried with threads, but the code is much more complex). I tried increasing MaxDegreeOfParallelism parameter, but it only limits the maximum number, so no luck here...

This is the code that I have currently:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        private static List<string> _list = new List<string>();
        private static int _toProcess = 0;

        static void Main(string[] args)
        {   
            for (int i = 0; i < 1000; ++i)
            {
                _list.Add("parameter" + i);
            }

            var w = new Worker();
            var w2 = new StringAnalyzer();

            Parallel.ForEach(_list, new ParallelOptions() { MaxDegreeOfParallelism = 32 }, item =>
            {
                ++_toProcess;
                string data = w.DoWork(item);
                w2.AnalyzeProcessedString(data);
            });

            Console.WriteLine("Finished");           
            Console.ReadKey();
        }

        static void Done(Task<string> t)
        {            
            Console.WriteLine(t.Result);
            --_toProcess;
        }
    }

    class Worker
    {
        public string DoWork(string par)
        {
            // It's a long running but not CPU heavy task (downloading stuff from the internet)
            System.Threading.Thread.Sleep(5000);            
            return par + " processed";
        }
    }

    class StringAnalyzer
    {
        public void AnalyzeProcessedString(string data)
        {
            // Rather short, not CPU heavy
            System.Threading.Thread.Sleep(1000);
            Console.WriteLine(data + " and analyzed");
        }
    }
}

解决方案

As L.B mentioned, .NET Framework has methods that performs I/O operations (requests to databases, web services etc.) using IOCP internally, they can be recognized by their names - it ends with Async by convention. So you could just use them to build robust scalable applications that can process multiple requests simultaneously.

EDIT: I've completely rewritten the code example with the modern best practices so it becomes much more readable, shorter and easy to use.

For the .NET 4.5 we can use approach:

class Program
{
    static void Main(string[] args)
    {
        var task = Worker.DoWorkAsync();
        task.Wait(); //stop and wait until our async method completed

        foreach (var item in task.Result)
        {
            Console.WriteLine(item);
        }

        Console.ReadLine();
    }
}

static class Worker
{
    public async static Task<IEnumerable<string>> DoWorkAsync()
    {
        List<string> results = new List<string>();

        for (int i = 0; i < 10; i++)
        {
            var request = (HttpWebRequest)WebRequest.Create("http://microsoft.com");
            using (var response = await request.GetResponseAsync())
            {
                results.Add(response.ContentType);
            }
        }

        return results;
    }
}

Here is the nice MSDN tutorial about async programming using async-await.

这篇关于如何指定的Parallel.ForEach执行的并行任务的数量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆