C# - Parallel Foreach缓慢创建线程

时间:2017-03-02 21:07:19

标签: c# multithreading parallel-processing task-parallel-library

我有一个IEnumerable,其中包含许多需要并行处理的项目。这些项目不是CPU密集型的。 理想情况下,这些项目应该在100个或更多线程上同时执行。

我已尝试使用Parallel.ForEach()执行此操作。这可行,但问题是新线程产生得太慢。在Parallel.Foreach()到达100个线程之前需要(太长)的时间。我知道有一个MaxDegreeOfParallelism属性,但这是一个最大值,而不是最小值。

有没有办法在100个线程上立即执行foreach? ThreadPool.SetMinThreads是我们希望避免的,因为它会对整个过程产生影响。

自定义分区程序是否可以解决方案?

2 个答案:

答案 0 :(得分:0)

  

我以超时5秒的速度ping了很多设备。如果只有4个线程(4个线程),你会如何尽快完成?

我将假设您在局域网上使用ping设备,并且每个设备都可通过IP地址识别和访问。

namespace PingManyDevices {

    public class DeviceChecker {                

        public async Task<PingReply[]> CheckAllDevices(IEnumerable<IPAddress> devices) {
            var pings = devices.Select(address => new Ping().SendPingAsync(address, 5000));
            return await Task.WhenAll(pings);
        }
        /***
        * Maybe push it a little further
        ***/ 
        public async Task<PingReply[]> CheckAllDevices(IEnumerable<IPAddress> devices) {
            var pings = devices.AsParallel().Select(address => new Ping().SendPingAsync(address, 5000));
            return await Task.WhenAll(pings);
        }          
    }
} 

答案 1 :(得分:-2)

我使用ThreadPool而不是Parallel成功了:

public static void ThreadForEach<T>(this IEnumerable<T> items, Action<T> action)
{
    var mres = new List<ManualResetEvent>();

    foreach (var item in items)
    {
        var mre = new ManualResetEvent(false);

        ThreadPool.QueueUserWorkItem((i) =>
        {
            action((T)i);
            mre.Set();
        }, item);

        mres.Add(mre);
    }

    mres.ForEach(mre => mre.WaitOne());
}

在我必须使用它的情况下,它比使用Parallel.ForEach的尝试运行得更快。我只能推测它是因为它试图使用已经存在的线程(而不是花费开销来创建新的线程)。