zoukankan      html  css  js  c++  java
  • Asp.Net任务Task和线程Thread

    Task是.NET4.0加入的,跟线程池ThreadPool的功能类似,用Task开启新任务时,会从线程池中调用线程,而Thread每次实例化都会创建一个新的线程。任务(Task)是架构在线程之上的,也就是说任务最终还是要抛给线程(Thread)去执行。

    1、首次构造一个Task对象时,他的状态是Created。
    2、当任务启动时,他的状态变成WaitingToRun。
    3、Task在一个线程上运行时,他的状态变成Running。
    4、任务停止运行,等待他的任何子任务时,状态变成WaitingForChildrenToComplete。
    5、任务完全结束时,它进入以下三个状态之一:RanToCompletion,Canceled或者Faulted。
    6、一个Task<TResult>运行完成时,可通过Task<TResult>的Result属性来查询任务的结果,
    7、一个Task或者Task<TResult>出错时,可以查询Task的Exception属性来获得任务抛出的未处理的异常,该属性总是返回一个AggregateException对象,他包含所有未处理的异常。
    8、为简化代码,Task提供了几个只读的Boolean属性,IsCanceled,IsFaulted,IsCompleted。
    9、注意,当Task处于RanToCompleted,Canceled或者Faulted状态时,IsCompleted返回True。
    10、为了判断一个Task是否成功完成,最简单的方法是:if(task.Status == TaskStatus.RanToCompletion)。
    11、task的ContinueWith方法用于在一个任务完成后发起一个新任务。

    任务Task和线程Thread的区别:

    static void Main(string[] args)
    {
        for (int i = 0; i < 5; i++)
        {
            new Thread(Run1).Start();
        }
        for (int i = 0; i < 5; i++)
        {
            Task.Run(() => { Run2(); });
        }
    }
    static void Run1()
    {
        Console.WriteLine("Thread Id =" + Thread.CurrentThread.ManagedThreadId);
    }
    static void Run2()
    {
        Console.WriteLine("Task调用的Thread Id =" + Thread.CurrentThread.ManagedThreadId);
    }

    Task使用方法

    创建Task有两种方式,一种是使用构造函数创建,另一种是使用 Task.Factory.StartNew 进行创建。如下代码所示

    1.使用构造函数创建Task

      Task t1 = new Task(MyMethod);

    2.使用Task.Factory.StartNew 进行创建Task

      Task t1 = Task.Factory.StartNew(MyMethod);

    多任务

    public void test()
        {
            Task[] tasks = new Task[10];
            for (int i = 0; i < 100; i++)
            {
                if (i % 2 == 0)
                {
                    tasks[i] = new Task(test2, (object)i);//传参,必须是obj
                }
                else
                {
                    tasks[i] = new Task(test1);
                }
                tasks[i].Start();
            }
            Task.WaitAll(tasks);//等待所有线程执行完成后才会继续往下执行
         
    //Task.WaitAll(tasks,5000);//最多等待5秒

    Response.Write("执行完成"); } private void test1() { //do } private void test2(object ourl) { //do }

    连续任务

    static void DownLoad(object str)
        {
           //下载文件
        }
        static void ReadNews(Task obj)
        {
            //读取文件
        }
        static void Main(string[] args)
        {
            Task task = new Task(DownLoad, "人民日报");
            Task task2 = task.ContinueWith(ReadNews);
            task.Start();
            //DownLoad执行完才执行ReadNews
        }

    Task返回值

    Task<string> t1 = Task.Factory.StartNew(() => "测试");
    t1.Wait();
    Console.WriteLine(t1.Result);
    Console.ReadLine();
    //返回值可以是任意的类型

    Task线程池最大数量

    这个TaskScheduler是微软开源的一个任务调度器

    LimitedConcurrencyLevelTaskScheduler.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Threading.Tasks;
    using System.Threading;
    
    /// <summary>
    ///LimitedConcurrencyLevelTaskScheduler 的摘要说明
    /// </summary>
    public class LimitedConcurrencyLevelTaskScheduler : TaskScheduler
    {
        // Indicates whether the current thread is processing work items.
        [ThreadStatic]
        private static bool _currentThreadIsProcessingItems;
    
        // The list of tasks to be executed 
        private readonly LinkedList<Task> _tasks = new LinkedList<Task>(); // protected by lock(_tasks)
    
        // The maximum concurrency level allowed by this scheduler. 
        private readonly int _maxDegreeOfParallelism;
    
        // Indicates whether the scheduler is currently processing work items. 
        private int _delegatesQueuedOrRunning = 0;
    
        // Creates a new instance with the specified degree of parallelism. 
        public LimitedConcurrencyLevelTaskScheduler(int maxDegreeOfParallelism)
        {
            if (maxDegreeOfParallelism < 1) throw new ArgumentOutOfRangeException("maxDegreeOfParallelism");
            _maxDegreeOfParallelism = maxDegreeOfParallelism;
        }
    
        // Queues a task to the scheduler. 
        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();
                }
            }
        }
    
        // Inform the ThreadPool that there's work to be executed for this scheduler. 
        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);
        }
    
        // Attempts to execute the specified task on the current thread. 
        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)
                // Try to run the task. 
                if (TryDequeue(task))
                    return base.TryExecuteTask(task);
                else
                    return false;
            else
                return base.TryExecuteTask(task);
        }
    
        // Attempt to remove a previously scheduled task from the scheduler. 
        protected sealed override bool TryDequeue(Task task)
        {
            lock (_tasks) return _tasks.Remove(task);
        }
    
        // Gets the maximum concurrency level supported by this scheduler. 
        public sealed override int MaximumConcurrencyLevel { get { return _maxDegreeOfParallelism; } }
    
        // Gets an enumerable of the tasks currently scheduled on this scheduler. 
        protected sealed override IEnumerable<Task> GetScheduledTasks()
        {
            bool lockTaken = false;
            try
            {
                Monitor.TryEnter(_tasks, ref lockTaken);
                if (lockTaken) return _tasks;
                else throw new NotSupportedException();
            }
            finally
            {
                if (lockTaken) Monitor.Exit(_tasks);
            }
        }
    }
    View Code

    使用方法

    控制多线程数量,并实时输出已完成任务数量

    protected void Page_Load(object sender, EventArgs e)
        {
            Response.Write("<script type="text/javascript">function load(i) {document.getElementById("now").innerHTML = i;}</script>");
            Response.Write("<span id='now'>0</span>/<span id='sum'>" + arr.Length + "</span>");
            Response.Flush();
    
            //设置最大线程数为5
            var scheduler = new LimitedConcurrencyLevelTaskScheduler(5);
            var Factory = new TaskFactory(scheduler);
            Task[] tasks = new Task[200];
            int res = 0;
            for (int i = 0; i < 200; i++)
            {
                Task tk = Factory.StartNew(() => downFile((object)i));
                tk.ContinueWith(t =>
                {
                    res++;
                    Response.Write("<script>load(" + res.ToString() + ")</script>");
                    Response.Flush();
                });
                tasks[i] = tk;
                
            }
            Task.WaitAll(tasks);
            Response.Write("完成");
        }
        private void downFile(object oid)
        {
            string iid= (string)id;
            //do...
            
        }

    Task使用过程中遇到的坑

    使用过程中发现有的task任务不执行,经过长时间调试发现在task调用的方法里很多C#方法不可用,

    例如HttpContext.Current.Request.Url、HttpContext.Current.Server.MapPath等方法不可用,真是坑

    //end



  • 相关阅读:
    UML建模之用例图关系
    python模块介绍
    Delphi操作XML(七)
    Delphi操作XML(一)
    Delphi操作XML(五)
    Delphi操作XML(六)
    Delphi操作XML(二)
    Delphi操作XML(四)
    Delphi操作XML(三)
    决心好好写cnblogs
  • 原文地址:https://www.cnblogs.com/webapi/p/10622614.html
Copyright © 2011-2022 走看看