比ThreadPool对象更好用的线程控制对象

Task对象很多人知道了(使用Task代替ThreadPool和Thread,
C#线程篇—Task(任务)和线程池不得不说的秘密(5))

相对的还有TaskScheduler 这个调度器,可以自定义调度器,只要重写TaskScheduler 方法就可以了
微软原来一早就对他进行了扩展Samples for Parallel Programming with the .NET Framework

这里写图片描述

转一下MSDN里的定义和调用方法

namespace System.Threading.Tasks.Schedulers
{

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading;

    class Program
    {
        static void Main()
        {
            LimitedConcurrencyLevelTaskScheduler lcts = new LimitedConcurrencyLevelTaskScheduler(1);
            TaskFactory factory = new TaskFactory(lcts);

            factory.StartNew(()=> 
                {
                    for (int i = 0; i < 500; i++)
                    {
                        Console.Write("{0} on thread {1}", i, Thread.CurrentThread.ManagedThreadId);
                    }
                }
            );

            Console.ReadKey();
        }
    }

    /// <summary>
    /// Provides a task scheduler that ensures a maximum concurrency level while
    /// running on top of the ThreadPool.
    /// </summary>
    public class LimitedConcurrencyLevelTaskScheduler : TaskScheduler
    {
        /// <summary>Whether the current thread is processing work items.</summary>
        [ThreadStatic]
        private static bool _currentThreadIsProcessingItems;
        /// <summary>The list of tasks to be executed.</summary>
        private readonly LinkedList<Task> _tasks = new LinkedList<Task>(); // protected by lock(_tasks)
        /// <summary>The maximum concurrency level allowed by this scheduler.</summary>
        private readonly int _maxDegreeOfParallelism;
        /// <summary>Whether the scheduler is currently processing work items.</summary>
        private int _delegatesQueuedOrRunning = 0; // protected by lock(_tasks)

        /// <summary>
        /// Initializes an instance of the LimitedConcurrencyLevelTaskScheduler class with the
        /// specified degree of parallelism.
        /// </summary>
        /// <param name="maxDegreeOfParallelism">The maximum degree of parallelism provided by this scheduler.</param>
        public LimitedConcurrencyLevelTaskScheduler(int maxDegreeOfParallelism)
        {
            if (maxDegreeOfParallelism < 1) throw new ArgumentOutOfRangeException("maxDegreeOfParallelism");
            _maxDegreeOfParallelism = maxDegreeOfParallelism;
        }

        /// <summary>Queues a task to the scheduler.</summary>
        /// <param name="task">The task to be queued.</param>
        protected sealed override void QueueTask(Task task)
        {
            // Add the task to the list of tasks to be processed.  If there aren't enough
            // delegates currently queued or running to process tasks, schedule another.
            lock (_tasks)
            {
                _tasks.AddLast(task);
                if (_delegatesQueuedOrRunning < _maxDegreeOfParallelism)
                {
                    ++_delegatesQueuedOrRunning;
                    NotifyThreadPoolOfPendingWork();
                }
            }
        }

        /// <summary>
        /// Informs the ThreadPool that there's work to be executed for this scheduler.
        /// </summary>
        private void NotifyThreadPoolOfPendingWork()
        {
            ThreadPool.UnsafeQueueUserWorkItem(_ =>
            {
                // Note that the current thread is now processing work items.
                // This is necessary to enable inlining of tasks into this thread.
                _currentThreadIsProcessingItems = true;
                try
                {
                    // Process all available items in the queue.
                    while (true)
                    {
                        Task item;
                        lock (_tasks)
                        {
                            // When there are no more items to be processed,
                            // note that we're done processing, and get out.
                            if (_tasks.Count == 0)
                            {
                                --_delegatesQueuedOrRunning;
                                break;
                            }

                            // Get the next item from the queue
                            item = _tasks.First.Value;
                            _tasks.RemoveFirst();
                        }

                        // Execute the task we pulled out of the queue
                        base.TryExecuteTask(item);
                    }
                }
                // We're done processing items on the current thread
                finally { _currentThreadIsProcessingItems = false; }
            }, null);
        }

        /// <summary>Attempts to execute the specified task on the current thread.</summary>
        /// <param name="task">The task to be executed.</param>
        /// <param name="taskWasPreviouslyQueued"></param>
        /// <returns>Whether the task could be executed on the current thread.</returns>
        protected sealed override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
        {
            // If this thread isn't already processing a task, we don't support inlining
            if (!_currentThreadIsProcessingItems) return false;

            // If the task was previously queued, remove it from the queue
            if (taskWasPreviouslyQueued) TryDequeue(task);

            // Try to run the task.
            return base.TryExecuteTask(task);
        }

        /// <summary>Attempts to remove a previously scheduled task from the scheduler.</summary>
        /// <param name="task">The task to be removed.</param>
        /// <returns>Whether the task could be found and removed.</returns>
        protected sealed override bool TryDequeue(Task task)
        {
            lock (_tasks) return _tasks.Remove(task);
        }

        /// <summary>Gets the maximum concurrency level supported by this scheduler.</summary>
        public sealed override int MaximumConcurrencyLevel { get { return _maxDegreeOfParallelism; } }

        /// <summary>Gets an enumerable of the tasks currently scheduled on this scheduler.</summary>
        /// <returns>An enumerable of the tasks currently scheduled.</returns>
        protected sealed override IEnumerable<Task> GetScheduledTasks()
        {
            bool lockTaken = false;
            try
            {
                Monitor.TryEnter(_tasks, ref lockTaken);
                if (lockTaken) return _tasks.ToArray();
                else throw new NotSupportedException();
            }
            finally
            {
                if (lockTaken) Monitor.Exit(_tasks);
            }
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
delphi线程池单元文件uThreadPool.pas,用法如下 type TRecvCommDataWorkItem=class(TWorkItem) public // updatetime,addtime:TDateTime; // orderid,ordertype,urljson,loadcount,savepath:string; url,Filename:string; total,order:Integer; _orderid:string; failedcount:Integer; IFCoverFile:Boolean; // 线程处理请求时触发的事件 procedure DealwithCommRecvData(Sender: TThreadsPool; WorkItem: TWorkItem; aThread: TProcessorThread); // 线程初始化时触发的事件 procedure TProcessorThreadInitializing(Sender: TThreadsPool; aThread:TProcessorThread); // 线程结束时触发的事件 procedure TProcessorThreadFinalizing(Sender: TThreadsPool; aThread:TProcessorThread); //任务队列空时触发的事件 procedure TQueueEmpty(Sender: TThreadsPool; EmptyKind: TEmptyKind); end; 先声明一个类 然后用法 FThreadPool := TThreadsPool.Create(nil); // 创建线程池 FThreadPool.ThreadsMin := 10; // 初始工作线程数 FThreadPool.ThreadsMax := 100; // 最大允许工作线程数 AWorkItem := TRecvCommDataWorkItem.Create; ISAllOverLoad:=False; AWorkItem.url:=urljson; AWorkItem.order:=i; AWorkItem.total:=JA.Count; AWorkItem.Filename:=savefilepath; AWorkItem._orderid:=orderid; AWorkItem.IFCoverFile:=IFCoverFile; FThreadPool.AddRequest(AWorkItem,True); // 向线程池分配一个任务 FThreadPool.OnProcessRequest := AWorkItem.DealwithCommRecvData; FThreadPool.OnThreadInitializing := AWorkItem.TProcessorThreadInitializing; FThreadPool.OnThreadFinalizing := AWorkItem.TProcessorThreadFinalizing; FThreadPool.OnQueueEmpty := AWorkItem.TQueueEmpty; 仔细看下线程池单元的函数说明轻松搞定。 procedure TRecvCommDataWorkItem.TQueueEmpty(Sender: TThreadsPool; EmptyKind: TEmptyKind); begin if EmptyKind=ekProcessingFinished then begin try if Assigned(geturl) then //存在的bug 如果下载文件存在的不行 begin //Sleep(200); //激活线程可能会发生在 休眠之前!! ISAl
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值