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)问题