سؤال

I want to execute a network based task (with a possible long timeout) on multiple peers simultaneously.

So i have the following code:

Parallel.ForEach(hosts, i => SomeLongRunningNetworkTask(i));

I noticed that from the sixth task on the execution is delayed for ~ 1 second.

So i changed the code to:

hosts.AsParallel()
                .WithDegreeOfParallelism(64)
                .ForAll(i => result.Add(SomeLongRunningNetworkTask(i)));

but the result is the same.

Output (on a Quad-Core):

Start: 44,00 ms
Start: 44,00 ms
Start: 44,00 ms
Start: 44,00 ms
Start: 44,00 ms
Start: 1025,06 ms
Start: 2024,12 ms
Start: 3024,17 ms
Start: 4024,23 ms
Start: 5024,29 ms
...

Is there an easy way to use PLINQ without this weird behavior, or am i missing something ?

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

namespace ConsoleApplicationParallelTest
{
    class Program
    {
        private DateTime Started { get; set; }

        static void Main(string[] args)
        {
            // for testing: All Subnet IP's: 
            var ips = new List<IPAddress>();
            for(int i=1 ; i< 255 ;i++)
                ips.Add( IPAddress.Parse( "192.168.10." + i ));

            var result = new Program().ExecuteAll(ips);
        }

        private List<Object> ExecuteAll(List<IPAddress> hosts)
        {
            Started = DateTime.Now;
            var result = new List<Object>();

            //Parallel.ForEach(hosts, i => SomeLongRunningNetworkTask(i));
            hosts.AsParallel()
                .WithDegreeOfParallelism(64)
                .ForAll(i => result.Add(SomeLongRunningNetworkTask(i))
                );

            return result;
        }

        private Object SomeLongRunningNetworkTask(Object o)
        {
            Console.WriteLine("Start: " + DateTime.Now.Subtract(Started).TotalMilliseconds.ToString("F2") + " ms");
            Thread.Sleep(60 * 1000);
            Console.WriteLine("End: " + DateTime.Now.Subtract(Started).TotalMilliseconds.ToString("F2") + " ms");
            return new Object();
        }
    }
}
هل كانت مفيدة؟

المحلول

When your threads call Thread.Sleep they are busy waiting and can't handle other of your hosts. My guess is the ThreadPool realizes it needs more resources and goes and creates more threads.

Try maybe running the test after setting ThreadPool.SetMinThreads to a bigger number.

Edit: As @henk commented. This almost never is a good idea.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top