Bug 8559

Summary: TaskScheduler passed with parallel options to Parallel.ForEach not used correctly
Product: [Mono] Class Libraries Reporter: Karol Gwaj <karol.gwaj>
Component: mscorlibAssignee: Jérémie Laval <jeremie.laval>
Status: RESOLVED FIXED    
Severity: normal CC: masafa, mono-bugs+mono
Priority: ---    
Version: 2.10.x   
Target Milestone: Untriaged   
Hardware: PC   
OS: All   
Tags: Is this bug a regression?: ---
Last known good build:

Description Karol Gwaj 2012-11-22 12:22:00 UTC
Looks like Parallel.ForEach is not using task scheduler passed with parallel options to create its own tasks,
It is setting correctly TaskScheduler.Current property of child tasks, but besides that it should also use it itself to create this tasks. 

So to "trick" it to use my custom TaskScheduler (which increases MaximumConcurrencyLevel) i have to wrap it into additional task and run it synchronously:

		public static void Main (string[] args)
		{
            ThreadPool.SetMaxThreads(100, 100);
            ThreadPool.SetMinThreads(100, 100);
			Console.WriteLine(TaskScheduler.Current.GetType());
			
            var task = new Task(delegate()
            {
				    Console.WriteLine(TaskScheduler.Current.GetType());
			        Parallel.ForEach(new[] { 1, 2, 3,4, 5, 6,7, 8, 9, 0, 1, 2 ,3, 4, 5 }, new ParallelOptions() { MaxDegreeOfParallelism = 100 }, i =>
                    {
                        Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
                        Thread.Sleep(5000);
                    });                
            });

            task.RunSynchronously(SimpleTaskScheduler.Default);


			Console.ReadKey();
		}
Comment 1 Karol Gwaj 2012-11-26 05:19:09 UTC
Line below (346) is the "bad boy" here:

int num = Math.Min (GetBestWorkerNumber(), options != null && options.MaxDegreeOfParallelism != -1 ? options.MaxDegreeOfParallelism : int.MaxValue);


GetBestWorkerNumber() method is using TaskScheduler from current context instead of the one passed with options. Instead it should look more or less like that:

int num = Math.Min ((options != null) && (options.TaskScheduler != null) ? options.TaskScheduler.MaximumConcurrencyLevel : GetBestWorkerNumber(), options != null && options.MaxDegreeOfParallelism != -1 ? options.MaxDegreeOfParallelism : int.MaxValue);
Comment 2 Jérémie Laval 2012-11-26 07:15:16 UTC
Thanks for the report. Fixed in mono-2-10 and master.