首页 > 代码库 > task 限制任务数量(转自msdn)

task 限制任务数量(转自msdn)

  1         public class LimitedConcurrencyLevelTaskScheduler : TaskScheduler  2         {  3             // Indicates whether the current thread is processing work items.  4             [ThreadStatic] private static bool _currentThreadIsProcessingItems;  5   6             // The maximum concurrency level allowed by this scheduler.   7             private readonly int _maxDegreeOfParallelism;  8   9             // The list of tasks to be executed  10             private readonly LinkedList<Task> _tasks = new LinkedList<Task>(); // protected by lock(_tasks) 11  12             // Indicates whether the scheduler is currently processing work items.  13             private int _delegatesQueuedOrRunning; 14  15             // Creates a new instance with the specified degree of parallelism.  16             public LimitedConcurrencyLevelTaskScheduler(int maxDegreeOfParallelism) 17             { 18                 if (maxDegreeOfParallelism < 1) throw new ArgumentOutOfRangeException("maxDegreeOfParallelism"); 19                 _maxDegreeOfParallelism = maxDegreeOfParallelism; 20             } 21  22             // Gets the maximum concurrency level supported by this scheduler.  23             public sealed override int MaximumConcurrencyLevel 24             { 25                 get { return _maxDegreeOfParallelism; } 26             } 27  28             // Queues a task to the scheduler.  29             protected sealed override void QueueTask(Task task) 30             { 31                 // Add the task to the list of tasks to be processed.  If there aren‘t enough  32                 // delegates currently queued or running to process tasks, schedule another.  33                 lock (_tasks) 34                 { 35                     _tasks.AddLast(task); 36                     if (_delegatesQueuedOrRunning < _maxDegreeOfParallelism) 37                     { 38                         ++_delegatesQueuedOrRunning; 39                         NotifyThreadPoolOfPendingWork(); 40                     } 41                 } 42             } 43  44             // Inform the ThreadPool that there‘s work to be executed for this scheduler.  45             private void NotifyThreadPoolOfPendingWork() 46             { 47                 ThreadPool.UnsafeQueueUserWorkItem(_ => 48                 { 49                     // Note that the current thread is now processing work items. 50                     // This is necessary to enable inlining of tasks into this thread. 51                     _currentThreadIsProcessingItems = true; 52                     try 53                     { 54                         // Process all available items in the queue. 55                         while (true) 56                         { 57                             Task item; 58                             lock (_tasks) 59                             { 60                                 // When there are no more items to be processed, 61                                 // note that we‘re done processing, and get out. 62                                 if (_tasks.Count == 0) 63                                 { 64                                     --_delegatesQueuedOrRunning; 65                                     break; 66                                 } 67  68                                 // Get the next item from the queue 69                                 item = _tasks.First.Value; 70                                 _tasks.RemoveFirst(); 71                             } 72  73                             // Execute the task we pulled out of the queue 74                             TryExecuteTask(item); 75                         } 76                     } 77                     // We‘re done processing items on the current thread 78                     finally 79                     { 80                         _currentThreadIsProcessingItems = false; 81                     } 82                 }, null); 83             } 84  85             // Attempts to execute the specified task on the current thread.  86             protected sealed override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) 87             { 88                 // If this thread isn‘t already processing a task, we don‘t support inlining 89                 if (!_currentThreadIsProcessingItems) return false; 90  91                 // If the task was previously queued, remove it from the queue 92                 if (taskWasPreviouslyQueued) 93                     // Try to run the task.  94                     if (TryDequeue(task)) 95                         return TryExecuteTask(task); 96                     else 97                         return false; 98                 return TryExecuteTask(task); 99             }100 101             // Attempt to remove a previously scheduled task from the scheduler. 102             protected sealed override bool TryDequeue(Task task)103             {104                 lock (_tasks)105                 {106                     return _tasks.Remove(task);107                 }108             }109 110             // Gets an enumerable of the tasks currently scheduled on this scheduler. 111             protected sealed override IEnumerable<Task> GetScheduledTasks()112             {113                 var lockTaken = false;114                 try115                 {116                     Monitor.TryEnter(_tasks, ref lockTaken);117                     if (lockTaken) return _tasks;118                     else throw new NotSupportedException();119                 }120                 finally121                 {122                     if (lockTaken) Monitor.Exit(_tasks);123                 }124             }125         }

使用方法

            // Create a scheduler that uses two threads.             var lcts = new LimitedConcurrencyLevelTaskScheduler(2);            var tasks = new List<Task>();            // Create a TaskFactory and pass it our custom scheduler.             var factory = new TaskFactory(lcts);            var cts = new CancellationTokenSource();            var t = factory.StartNew(() =>                {                }, cts.Token);            tasks.Add(t);            Task.WaitAll(tasks.ToArray());            cts.Dispose();
或者
       
Task ttt=new Task((() => {}));
       ttt.Start(lcts);
 

 

task 限制任务数量(转自msdn)