ThreadPoolTaskScheduler.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / BCL / System / Threading / Tasks / ThreadPoolTaskScheduler.cs / 1305376 / ThreadPoolTaskScheduler.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
// 
// TaskScheduler.cs 
//
// [....] 
//
// This file contains the primary interface and management of tasks and queues.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 

using System; 
using System.Security; 
using System.Diagnostics.Contracts;
using System.Collections.Generic; 
using System.Text;
using System.Diagnostics.Eventing;

namespace System.Threading.Tasks 
{
    ///  
    /// An implementation of TaskScheduler that uses the ThreadPool scheduler 
    /// 
    internal sealed class ThreadPoolTaskScheduler: TaskScheduler 
    {
        /// 
        /// Constructs a new ThreadPool task scheduler object
        ///  
        internal ThreadPoolTaskScheduler()
        { 
        } 

        // static delegate for threads allocated to handle LongRunning tasks. 
        private static ParameterizedThreadStart s_longRunningThreadWork = new ParameterizedThreadStart(LongRunningThreadWork);
        private static void LongRunningThreadWork(object obj)
        {
            Task t = obj as Task; 
            Contract.Assert(t != null, "TaskScheduler.LongRunningThreadWork: t is null");
            t.ExecuteEntry(false); 
        } 

        ///  
        /// Schedules a task to the ThreadPool.
        /// 
        /// The task to schedule.
        [SecurityCritical] 
        protected internal override void QueueTask(Task task)
        { 
#if !FEATURE_PAL    // PAL doesn't support  eventing 
            if (TplEtwProvider.Log.IsEnabled(EventLevel.Verbose, ((EventKeywords)(-1))))
            { 
                Task currentTask = Task.InternalCurrent;
                Task creatingTask = task.m_parent;

                TplEtwProvider.Log.TaskScheduled(this.Id, currentTask == null ? 0 : currentTask.Id, 
                                                 task.Id, creatingTask == null? 0 : creatingTask.Id,
                                                 (int) task.Options); 
            } 
#endif
 
            if ((task.Options & TaskCreationOptions.LongRunning) != 0)
            {
                // Run LongRunning tasks on their own dedicated thread.
                Thread thread = new Thread(s_longRunningThreadWork); 
                thread.IsBackground = true; // Keep this thread from blocking process shutdown
                thread.Start(task); 
            } 
            else
            { 
                // Normal handling for non-LongRunning tasks.
                bool forceToGlobalQueue = ((task.Options & TaskCreationOptions.PreferFairness) != 0);
                ThreadPool.UnsafeQueueCustomWorkItem(task, forceToGlobalQueue);
            } 
        }
 
        ///  
        /// This internal function will do this:
        ///   (1) If the task had previously been queued, attempt to pop it and return false if that fails. 
        ///   (2) Propagate the return value from Task.ExecuteEntry() back to the caller.
        ///
        /// IMPORTANT NOTE: TryExecuteTaskInline will NOT throw task exceptions itself. Any wait code path using this function needs
        /// to account for exceptions that need to be propagated, and throw themselves accordingly. 
        /// 
        [SecurityCritical] 
        protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) 
        {
            // If the task was previously scheduled, and we can't pop it, then return false. 
            if (taskWasPreviouslyQueued && !ThreadPool.TryPopCustomWorkItem(task))
                return false;

            // Propagate the return value of Task.ExecuteEntry() 
            bool rval = false;
            try 
            { 
                rval = task.ExecuteEntry(false); // calling the TaskBase override here, because it handles switching Task.Current etc.
            } 
            finally
            {
                //   Only call NWIP() if task was previously queued
                if(taskWasPreviouslyQueued) NotifyWorkItemProgress(); 
            }
 
            return rval; 
        }
 
        [SecurityCritical]
        protected internal override bool TryDequeue(Task task)
        {
            // just delegate to TP 
            return ThreadPool.TryPopCustomWorkItem(task);
        } 
 
        [SecurityCritical]
        protected override IEnumerable GetScheduledTasks() 
        {
            return FilterTasksFromWorkItems(ThreadPool.GetQueuedWorkItems());
        }
 
        private IEnumerable FilterTasksFromWorkItems(IEnumerable tpwItems)
        { 
            foreach (IThreadPoolWorkItem tpwi in tpwItems) 
            {
                if (tpwi is Task) 
                {
                    yield return (Task)tpwi;
                }
            } 
        }
 
        ///  
        /// Notifies the scheduler that work is progressing (no-op).
        ///  
        internal override void NotifyWorkItemProgress()
        {
            ThreadPool.NotifyWorkItemProgress();
        } 

        ///  
        /// This is the only scheduler that returns false for this property, indicating that the task entry codepath is unsafe (CAS free) 
        /// since we know that the underlying scheduler already takes care of atomic transitions from queued to non-queued.
        ///  
        internal override bool RequiresAtomicStartTransition
        {
            get { return false; }
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
// 
// TaskScheduler.cs 
//
// [....] 
//
// This file contains the primary interface and management of tasks and queues.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 

using System; 
using System.Security; 
using System.Diagnostics.Contracts;
using System.Collections.Generic; 
using System.Text;
using System.Diagnostics.Eventing;

namespace System.Threading.Tasks 
{
    ///  
    /// An implementation of TaskScheduler that uses the ThreadPool scheduler 
    /// 
    internal sealed class ThreadPoolTaskScheduler: TaskScheduler 
    {
        /// 
        /// Constructs a new ThreadPool task scheduler object
        ///  
        internal ThreadPoolTaskScheduler()
        { 
        } 

        // static delegate for threads allocated to handle LongRunning tasks. 
        private static ParameterizedThreadStart s_longRunningThreadWork = new ParameterizedThreadStart(LongRunningThreadWork);
        private static void LongRunningThreadWork(object obj)
        {
            Task t = obj as Task; 
            Contract.Assert(t != null, "TaskScheduler.LongRunningThreadWork: t is null");
            t.ExecuteEntry(false); 
        } 

        ///  
        /// Schedules a task to the ThreadPool.
        /// 
        /// The task to schedule.
        [SecurityCritical] 
        protected internal override void QueueTask(Task task)
        { 
#if !FEATURE_PAL    // PAL doesn't support  eventing 
            if (TplEtwProvider.Log.IsEnabled(EventLevel.Verbose, ((EventKeywords)(-1))))
            { 
                Task currentTask = Task.InternalCurrent;
                Task creatingTask = task.m_parent;

                TplEtwProvider.Log.TaskScheduled(this.Id, currentTask == null ? 0 : currentTask.Id, 
                                                 task.Id, creatingTask == null? 0 : creatingTask.Id,
                                                 (int) task.Options); 
            } 
#endif
 
            if ((task.Options & TaskCreationOptions.LongRunning) != 0)
            {
                // Run LongRunning tasks on their own dedicated thread.
                Thread thread = new Thread(s_longRunningThreadWork); 
                thread.IsBackground = true; // Keep this thread from blocking process shutdown
                thread.Start(task); 
            } 
            else
            { 
                // Normal handling for non-LongRunning tasks.
                bool forceToGlobalQueue = ((task.Options & TaskCreationOptions.PreferFairness) != 0);
                ThreadPool.UnsafeQueueCustomWorkItem(task, forceToGlobalQueue);
            } 
        }
 
        ///  
        /// This internal function will do this:
        ///   (1) If the task had previously been queued, attempt to pop it and return false if that fails. 
        ///   (2) Propagate the return value from Task.ExecuteEntry() back to the caller.
        ///
        /// IMPORTANT NOTE: TryExecuteTaskInline will NOT throw task exceptions itself. Any wait code path using this function needs
        /// to account for exceptions that need to be propagated, and throw themselves accordingly. 
        /// 
        [SecurityCritical] 
        protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) 
        {
            // If the task was previously scheduled, and we can't pop it, then return false. 
            if (taskWasPreviouslyQueued && !ThreadPool.TryPopCustomWorkItem(task))
                return false;

            // Propagate the return value of Task.ExecuteEntry() 
            bool rval = false;
            try 
            { 
                rval = task.ExecuteEntry(false); // calling the TaskBase override here, because it handles switching Task.Current etc.
            } 
            finally
            {
                //   Only call NWIP() if task was previously queued
                if(taskWasPreviouslyQueued) NotifyWorkItemProgress(); 
            }
 
            return rval; 
        }
 
        [SecurityCritical]
        protected internal override bool TryDequeue(Task task)
        {
            // just delegate to TP 
            return ThreadPool.TryPopCustomWorkItem(task);
        } 
 
        [SecurityCritical]
        protected override IEnumerable GetScheduledTasks() 
        {
            return FilterTasksFromWorkItems(ThreadPool.GetQueuedWorkItems());
        }
 
        private IEnumerable FilterTasksFromWorkItems(IEnumerable tpwItems)
        { 
            foreach (IThreadPoolWorkItem tpwi in tpwItems) 
            {
                if (tpwi is Task) 
                {
                    yield return (Task)tpwi;
                }
            } 
        }
 
        ///  
        /// Notifies the scheduler that work is progressing (no-op).
        ///  
        internal override void NotifyWorkItemProgress()
        {
            ThreadPool.NotifyWorkItemProgress();
        } 

        ///  
        /// This is the only scheduler that returns false for this property, indicating that the task entry codepath is unsafe (CAS free) 
        /// since we know that the underlying scheduler already takes care of atomic transitions from queued to non-queued.
        ///  
        internal override bool RequiresAtomicStartTransition
        {
            get { return false; }
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK