Inheritance: IDisposable
Exemple #1
0
        /// <param name="threadCount">The desired number of threads to create. If not specified, the default is based on the number of processors available.</param>
        /// <param name="createBackgroundThreads">Whether to create background threads for processing work. Non-background threads will block the program from exiting until their work is complete.</param>
        /// <param name="timeProvider">The time provider used to measure elapsed times during work item processing.</param>
        /// <param name="comThreadingModel">If you don't already know what this is, you probably don't care about it.</param>
        /// <param name="name">A name used to identify the threads owned by this group for debugging purposes.</param>
        /// <param name="enableCoarseTime">If set, a background thread will be created responsible for reading the system clock. This will improve main thread step performance at the cost of extra CPU usage.</param>
        public ThreadGroup(
            int?threadCount = null,
            bool createBackgroundThreads     = false,
            ITimeProvider timeProvider       = null,
            ApartmentState comThreadingModel = ApartmentState.Unknown,
            string name           = null,
            bool enableCoarseTime = false
            )
        {
            Name                    = name;
            ThreadCount             = Math.Min(threadCount.GetValueOrDefault(Environment.ProcessorCount), MaximumThreadCount);
            CreateBackgroundThreads = createBackgroundThreads;
            TimeProvider            = timeProvider ?? Time.DefaultTimeProvider;
            COMThreadingModel       = comThreadingModel;

            Threads = new GroupThread[ThreadCount];
            for (int i = 0; i < Threads.Length; i++)
            {
                Threads[i] = new GroupThread(this, i);
            }

            SynchronizationContext = SynchronizationContext.Current;
            if (enableCoarseTime)
            {
                TimeThread = new Thread(TimeThreadProc)
                {
                    IsBackground = true
                };
                TimeThread.Start();
            }
        }
Exemple #2
0
        private static bool ThreadMainStep(WeakReference <GroupThread> weakSelf, ref int queueIndex, out bool moreWorkRemains)
        {
            // We hold the strong reference at method scope so we can be sure it doesn't get held too long
            GroupThread strongSelf = null;

            moreWorkRemains = false;

            // If our owner object has been collected, abort
            if (!weakSelf.TryGetTarget(out strongSelf))
            {
                return(false);
            }

            // If our owner object has been disposed, abort
            if (strongSelf.IsDisposed)
            {
                return(false);
            }

            int queueCount;

            IWorkQueue[] queues;
            lock (strongSelf.Queues) {
                queueCount = strongSelf.Queues.Count;
                queues     = strongSelf.Queues.GetBuffer();
            }

            strongSelf.Owner.ThreadBeganWorking();

            for (int i = 0; i < queueCount; i++)
            {
                // We round-robin select a queue from our pool every tick and then step it
                IWorkQueue queue = null;
                if (queueIndex < queueCount)
                {
                    queue = queues[queueIndex];
                }

                queueIndex = (queueIndex + 1) % queueCount;

                if (queue != null)
                {
                    bool exhausted;
                    int  processedItemCount = queue.Step(out exhausted);

                    // HACK: If we processed at least one item in this queue, but more items remain,
                    //  make sure the caller knows not to go to sleep.
                    if (processedItemCount > 0)
                    {
                        moreWorkRemains |= !exhausted;
                    }
                }
            }

            strongSelf.Owner.ThreadBecameIdle();

            GC.KeepAlive(strongSelf);
            return(true);
        }
Exemple #3
0
 internal void RegisterQueuesForNewThread(GroupThread newThread)
 {
     lock (QueueList)
         foreach (var queue in QueueList)
         {
             newThread.RegisterQueue(queue);
         }
 }
Exemple #4
0
        private void SpawnThread(bool force)
        {
            // Just in case thread state gets out of sync...
            if ((Threads.Count >= MaximumThreadCount) && !force)
            {
                return;
            }

            Interlocked.Exchange(ref LastTimeThreadWasIdle, TimeProvider.Ticks);
            var thread = new GroupThread(this);

            Threads.Add(thread);

            Thread.MemoryBarrier();

            HasNoThreads       = false;
            CanMakeNewThreads  = Threads.Count < MaximumThreadCount;
            CurrentThreadCount = Threads.Count;

            Thread.MemoryBarrier();
        }
Exemple #5
0
        private static ThreadIdleManager ThreadMainStep(
            WeakReference <GroupThread> weakSelf, ref bool running
            )
        {
            // We hold the strong reference at method scope so we can be sure it doesn't get held too long
            GroupThread strongSelf = null;

            // If our owner object has been collected or disposed, abort
            if (!weakSelf.TryGetTarget(out strongSelf) || strongSelf.IsDisposed)
            {
                running = false;
                return(null);
            }

            if (strongSelf.IdleManager.BeginRunning() && strongSelf.PerformWork())
            {
                return(strongSelf.IdleManager);
            }
            else
            {
                return(null);
            }
        }