/// <summary> /// Adjust scheduling options. /// </summary> /// <param name="settings">The new scheduling options. </param> public void SetSchedulingOptions(MultiThreadSchedulingSettings settings) { if (_disposalComplete != null) { throw new ObjectDisposedException("Cannot set the number of threads for a disposed scheduler. "); } int numThreads; if ((settings.Mode & MultiThreadCreationMode.OneThreadPerLogicalCpu) != 0) { // FIXME filter this list based on process CPU affinity var cpuInfo = CpuTopologyInfo.GetList(); if ((settings.Mode & MultiThreadCreationMode.OneThreadPerCpuCore) == MultiThreadCreationMode.OneThreadPerCpuCore) { numThreads = CpuTopologyInfo.CountNumberOfCores(cpuInfo); } else { numThreads = cpuInfo.Length; } settings.NumberOfThreads = numThreads; } else { numThreads = settings.NumberOfThreads; if (numThreads <= 0) { throw new ArgumentOutOfRangeException($"{nameof(MultiThreadSchedulingSettings)}.{nameof(MultiThreadSchedulingSettings.NumberOfThreads)} is out of range: {numThreads}"); } } // Cap at CPU quota, if requested. // FIXME For dynamic updates to CPU quota we should read the quota ourselves if ((settings.Mode & MultiThreadCreationMode.CapThreadsAtCpuQuota) != 0) { numThreads = Math.Min(numThreads, Environment.ProcessorCount); } if (numThreads == 0) { numThreads = 1; } SetNumberOfThreads(numThreads, settings.ThreadPriority); // Publish new options, if SetNumberOfThreads does not fail SchedulingOptions = settings; }
/// <summary> /// Prepare to accept tasks. No worker threads are started initially. /// </summary> /// <param name="executor">Object or state for processing work items. /// </param> /// <param name="syncContext">The synchronization context to set on all /// worker threads. </param> /// <param name="logger">Logger to observe important events during this /// scheduler's lifetime. </param> public MultiThreadScheduler(TExecutor executor, SynchronizationContext?syncContext, ISchedulingLogger?logger) { Logger = logger ?? new NullSchedulingLogger(); Executor = executor; WorkerSyncContext = syncContext; // Initial settings SchedulingOptions = new MultiThreadSchedulingSettings { Mode = MultiThreadCreationMode.CustomNumberOfThreads, ThreadPriority = ThreadPriority.Normal, NumberOfThreads = 0 }; }