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

Posted 月渊

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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                 try
115                 {
116                     Monitor.TryEnter(_tasks, ref lockTaken);
117                     if (lockTaken) return _tasks;
118                     else throw new NotSupportedException();
119                 }
120                 finally
121                 {
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)的主要内容,如果未能解决你的问题,请参考以下文章

Swift新async/await并发中利用Task防止指定代码片段执行的数据竞争(Data Race)问题

Swift新async/await并发中利用Task防止指定代码片段执行的数据竞争(Data Race)问题

Leetcode:Task Scheduler分析和实现

Celery:当排队太多时阻止添加更多任务

Task2

如何限制运行的并行任务数量? [关闭]