异步和多线程,委托异步调用,Thread,ThreadPool,Task,Parallel,CancellationTokenSource

1 进程-线程-多线程,同步和异步
2 异步使用和回调
3 异步参数
4 异步等待
5 异步返回值

5 多线程的特点:不卡主线程、速度快、无序性
7 thread:线程等待,回调,前台线程/后台线程,
8 threadpool:线程池使用,设置线程池,ManualResetEvent
9 Task初步接触

10 task:waitall waitany continueWhenAny continueWhenAll 

11并行运算Parallel

12 异常处理、线程取消、多线程的临时变量和lock
13 Await/Async

                                                             Anker_张(博客园)http://www.cnblogs.com/AnkerZhang/ 

//简单同步委托、方法调用 val是返回值
            Func<int, string> func1 = i =>
            {
                string result = i + "变返回值";
                return result;
            };
            string val= func1.Invoke(100);
 //委托、方法异步调用
            func1.BeginInvoke(100, null, null);//开启新的进程去执行方法

            IAsyncResult asyncResult = null;//表示异步操作的状态。
            AsyncCallback callback = t => //回调函数方法处理
            {
                Console.WriteLine(t.Equals(asyncResult));//运行起来是true
                Console.WriteLine(t.AsyncState);//t.AsyncState回调函数所需要传的参数
                Console.WriteLine("这里是回调函数 {0}", Thread.CurrentThread.ManagedThreadId);//表示线程ID
            };
            asyncResult = func1.BeginInvoke(100, callback, "我是回调函数参数");//参数1:委托所需int参数,2:穿入回调函数,3:回调函数参数,返回值是回调函数
            bool b = asyncResult.IsCompleted;//指示异步操作是否已完成。 返回结果: 如果操作完成则为 true,否则为 false。
            asyncResult.AsyncWaitHandle.WaitOne();//一直等待
            asyncResult.AsyncWaitHandle.WaitOne(-1);//一直等待
            asyncResult.AsyncWaitHandle.WaitOne(1000);//等待1000毫秒,超时就不等待了
            func1.EndInvoke(asyncResult);//会一直等待回调函数执行完成

委托的异步调用
 异步多线程的三大特点:
1 同步方法卡界面,原因是主线程被占用;异步方法不卡界面,原因是计算交给了别的线程,主线程空闲
2 同步方法慢,原因是只有一个线程计算;异步方法快,原因是多个线程同时计算,但是更消耗资源,不宜太多
3 异步多线程是无序的,启动顺序不确定、执行时间不确定、结束时间不确定

     /// <summary>
        /// 执行动作:耗时而已
        /// </summary>
        private static void TestThread(string threadName)
        {
            Console.WriteLine("TestThread Start  Name={2}当前线程的id:{0},当前时间为{1},", System.Threading.Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff"), threadName);
            long sum = 0;
            for (int i = 1; i < 999999999; i++)
            {
                sum += i;
            }
            Console.WriteLine("TestThread End  Name={2}当前线程的id:{0},当前时间为{1},计算结果{3}", System.Threading.Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff"), threadName, sum);
        }
//多线程
            Stopwatch watch = new Stopwatch();//用于计时器
            watch.Start();//开始计时
            Console.WriteLine();
            Console.WriteLine("***********************btnThread_Click Start 主线程id {0}**********************************", Thread.CurrentThread.ManagedThreadId);
            List<Thread> threadList = new List<Thread>();
            for (int i = 0; i < 5; i++)
            {
                string name = string.Format("btnThread_Click_{0}", i);
                ThreadStart method = () => TestThread(name);
                Thread thread = new Thread(method);//1 默认前台线程:程序退出后,计算任务会继续
                thread.IsBackground = true;//2 后台线程:程序退出,计算立即结束
                thread.Start();//启动线程
                threadList.Add(thread);//添加在集合
            }

            foreach (Thread thread in threadList)
            {
                thread.Join();///等待每个线程执行完毕
            }
            watch.Stop();//结束计算时间
            Console.WriteLine("**********************btnThread_Click   End 主线程id {0} {1}************************************", Thread.CurrentThread.ManagedThreadId, watch.ElapsedMilliseconds);
            Console.WriteLine();

线程池(ThreadPool)

可设置线程池线程数量,把线程留在程序中

每次可循环使用,不用再去和操作系统申请线程

//线程池
            ManualResetEvent mre = new ManualResetEvent(false);
            for (int i = 0; i < 5; i++)
            {
                string name = string.Format("ThreadPool{0}", i);
                WaitCallback method = t => {
                    Console.WriteLine("我是异步调用方法参数:{0}", t.ToString());
                    mre.Set(); //打开 mre.Reset();//关闭
                };
                ThreadPool.QueueUserWorkItem(method, name);
            }
            Console.WriteLine("我们来干点别的。。。。");
            Console.WriteLine("我们来干点别的。。。。");
            Console.WriteLine("我们来干点别的。。。。");
            Console.WriteLine("我们来干点别的。。。。");
            mre.WaitOne();//判断线程是否全部执行完成
            ThreadPool.SetMaxThreads(8, 8);//设置最大线程池数量和IO线程池运行数量
            ThreadPool.SetMinThreads(8, 8);
            int workerThreads;
            int ioThreads;
            ThreadPool.GetMaxThreads(out workerThreads, out ioThreads);//获取当前线程状况

Task

CRL4.0

引用 Task是基于线程池开发,效率提升

//Task CRL4.0引用 Task是基于线程池开发,效率提升
            {
                TaskFactory taskFactory = new TaskFactory();//创建Task工厂
                for (int i = 0; i < 5; i++)
                {
                    string name = string.Format("Async_{0}", i);
                    Action act = () => TestThread(name);//这个方法执行动作:耗时而已
                    Task task = taskFactory.StartNew(act);//这里也可以 Task task =new Task(act);
                    task.Start();//启动Task
                }
            }
            //Task一下方法比较效率高推荐使用
            {
                TaskFactory taskFactory = new TaskFactory();//创建Task工厂
                List<Task> taskList = new List<Task>();//创建Task集合
                Action<object> act = o => Console.WriteLine(o.ToString());
                Task task = taskFactory.StartNew(act, "参数1");//创建一个新的委托Task方法
                taskList.Add(task);
                taskList.Add( taskFactory.StartNew(s => Console.WriteLine(s.ToString()), "参数2"));
                Task any = taskFactory.ContinueWhenAny(taskList.ToArray(), t =>//taskList中任意任务线程执行完毕,就执行该方法(异步执行)
                {
                    //t.AsyncState
                    Console.WriteLine("这里是ContinueWhenAny {0}", Thread.CurrentThread.ManagedThreadId);//打印线程ID
                });
                Task all = taskFactory.ContinueWhenAll(taskList.ToArray(), tList =>//taskList中全部任务线程执行完毕,就执行该方法(异步执行)
                {
                    Console.WriteLine("这里是ContinueWhenAll {0}", Thread.CurrentThread.ManagedThreadId);
                });
                Task.WaitAny(taskList.ToArray());//执行的线程等待某一个task的完成
                Task.WaitAll(taskList.ToArray());//执行的线程等待全部的task的完成
            }

Parallel 并行计算
Parallel是基于Task开发,并行计算与Task.WaitAll执行等待结果不同的是:Task.WaitAll在执行时主线程在锁死等在子线程执行完成
Parallel是主线程也同样随机分配一个子线程去执行任务,Parallel比Task少开启一个线程

//Parallel 并行计算
            Parallel.Invoke(() => TestThread("btnParallel_Click_0")//这个方法执行动作:耗时而已
                          , () => TestThread("btnParallel_Click_1")//这个方法执行动作:耗时而已
                          , () => TestThread("btnParallel_Click_2")//这个方法执行动作:耗时而已
                          , () => TestThread("btnParallel_Click_3")//这个方法执行动作:耗时而已
                          , () => TestThread("btnParallel_Click_4"));//这个方法执行动作:耗时而已
            //等于使用4个task,然后主线程同步invoke一个委托  然后主线程waitall
            Parallel.For(6, 10, t =>
            {
                string name = string.Format("For btnParallel_Click_{0}", t);
                TestThread(name);//这个方法执行动作:耗时而已
            });
            ParallelOptions parallelOptions = new ParallelOptions()
            {
                MaxDegreeOfParallelism = 5//实例所允许的最大并行度。
            };
            Parallel.For(6, 15, parallelOptions, (t, state) =>
            {
                string name = string.Format("btnParallel_Click_{0}", t);
                TestThread(name);
                state.Break();//退出单次循环
                state.Stop();//退出全部的循环
                return;
            });

异常处理、线程取消、多线程的临时变量和线程安全lock

//异常处理、线程取消、多线程的临时变量和线程安全lock
          CancellationTokenSource cts = new CancellationTokenSource();//线程取消专用实例
                TaskFactory taskFactory = new TaskFactory();
                List<Task> taskList = new List<Task>();
                for (int i = 0; i < 20; i++)
                {
                    Action<object> act = t =>
                    {
                        try
                        {
                            if (t.ToString().Equals("10"))//模拟当i=10抛异常
                            {
                                throw new Exception(string.Format("{0} 执行失败", t));
                            }
                            if (!cts.IsCancellationRequested)//是否被取消
                            {
                                Console.WriteLine("{0} 执行成功", t);
                            }
                            else
                            {
                                Console.WriteLine("{0} 被取消", t);
                            }
                        }
                        catch (Exception ex)
                        {
                            cts.Cancel();// 传达取消请求。
                            Console.WriteLine("子线程异常 {0}", ex.Message);
                        }

                    };
                    taskFactory.StartNew(act, i);
                    Task task = taskFactory.StartNew(act, i, cts.Token);//加上 cts.Token 如果被取消集合里面剩余的线程就不会启动了
                    taskList.Add(task);
                }

                Task.WaitAll(taskList.ToArray());
                ///多线程的临时变量和线程安全lock
                ///每次实例新对象防止变量访问冲突
                ///如果同时访问同一变量加上Lock
                ///private static object obj = new object();
                ///lock (obj)
                ///{
                ///     锁住啦
                ///}
时间: 2024-10-20 05:41:24

异步和多线程,委托异步调用,Thread,ThreadPool,Task,Parallel,CancellationTokenSource的相关文章

[多线程]thread,threadpool,task及TPL知识点整理

简单理解 Thread:是一个指令序列,个体对象. Threadpool:在使用Thread的过程中,程序员要为每个希望并发的序列new一个线程,很麻烦,因此希望有一个统一管理线程的方法,程序员就不需要关注线程的申请管理问题,所以就对Thread进行一系列封装,有了ThreadPool.使用Threadpool,把需要并发的序列添加进线程池,线程池根据其线程列表中的线程的空闲情况,动态为并发序列申请线程. Task:再后来,程序员发现在使用Threadpool的过程当中还是存在很多不便,比如:(

.net 多线程 Thread ThreadPool Task

先准备一个耗时方法 /// <summary>/// 耗时方法/// </summary>/// <param name="name"></param>private void DoSomeThing(string name){                 Console.WriteLine($"开始执行{name}, {Thread.CurrentThread.ManagedThreadId.ToString("

一位牛人的多线程和异步调用文章

转自小顾问原文 一位牛人的多线程和异步调用文章 首先申明:这篇文章不是我写的,我看到的一位牛人的,自己慢慢的消化了…… 摘要:本章讨论与智能客户端应用程序中多线程的使用有关的问题.为了最大限度地提高智能客户端应用程序的响应能力,需要仔细考虑如何和何时使用多线程.线程可以大大提高应用程序的可用性和性能,但是当您确定它们将如何与用户界面交互时,需要对其进行非常仔细的考虑. 线程是基本执行单元.单线程执行一系列应用程序指令,并且在应用程序中从头到尾都经由单一的逻辑路径.所有的应用程序都至少有一个线程,

第一章 管理程序流 之 实现多线程和异步处理

1. 概述 本章主要讲解.net4.5如何实现多线程和异步处理的相关内容. 2. 主要内容 2.1 理解线程 ① 使用Thread类   public static class Program   {       public static void ThreadMethod()       {           for (int i = 0; i < 10; i++)           {               Console.WriteLine(“ThreadProc: {0}”,

NET中的并行编程(TPL)——多线程、异步、任务和并行计算

https://masuit.com/1201 谈一谈.NET中的并行编程(TPL)——多线程.异步.任务和并行计算 懒得勤快 发表于2018-04-26 19:41:00 | 最后修改于2018-06-27 23:44:40 .NET 多线程 异步 高并发 分类:.NET开发技术 | 评论总数:0条 | 热度:2243℃ 我要编辑 写在前面: 在做了几个月的高并发项目的过程中,其实发现自己真的提升了不少,所以也想把这段时间的收获分享给大家,然后写这篇文章发现,写下来是一发不可收拾,所以这篇文章

初步谈谈 C# 多线程、异步编程与并发服务器

多线程与异步编程可以达到避免调用线程异步阻塞作用,但是两者还是有点不同. 多线程与异步编程的异同: 1.线程是cpu 调度资源和分配的基本单位,本质上是进程中的一段并发执行的代码. 2.线程编程的思维符合正常人的思维习惯,线程中的处理程序依然是顺序执行,所以编程起来比较方便,但是缺点也是明显的,多线程的使用会造成多线程之间的上下文切换带来系统花销,并且共享变量之间也是会造成死锁的问题. 3.因为异步操作无须额外的线程负担,并且使用回调的方式进行处理,在设计良好的情况下,处理函数可以不必使用共享变

13、Android的多线程与异步任务

课程目标:学习Android中异步操作的三大方式 重点难点:Handler与线程的关系   Handler消息队列的实现 考核目标: 使用Handler是异步的,它会建立新线程么? no Handler是在主线程内么? Handler的post 和 sentMessage方法,使用的是一个队列还是两个? 子线程中建立一个handler,然后sendMessage会怎样? 子线程建立handler , 构造的时候传入主线程的,Looper?  Yes          一.回顾Java多线程基础

异步、多线程解惑

关于多线程和异步相信不少人都有疑问,它们之间到底有什么区别呢? 从知乎上看见一个比喻还是比较好理解的: 现在假设整个城市就只有1个火车,1个售票员,每个乘客咨询售票员后需要思考1分钟再决定买哪趟车的票. 异步 在买票的人咨询后,需要思考1分钟,马上靠边站,但不用重新排队,什么时候想清楚可以立马去跟售票员去买票.在该人站在旁边思考的时候,后面的人赶紧上去接着买.这时候队伍是很快的挪动的,没有阻塞,售票员的最大化的效率. 多线程 火车站开n个窗口(但还是只有一个人售票),外面同时排n个队,售票员回答

异步与多线程的区别

当我们在遇到需要长时间执行的任务时候,比如读取一个文件,远程服务调用.这些功能都会阻塞主线程,造成主线程卡死,从而造成一种软件崩溃的假象.这样的情况下,我们都会想到使用异步多线程的技术去解决这个问题. 我在学习NodeJs的之前,一直以为异步和多线程是同一个概念,当我接触到Node的时候,感觉自己遭到了当头棒喝,Node是单线程的,也不支持多线程,但是他的很多操作都是异步的,比如文件的读取.这让我很沮丧,也花了很长时间去理解异步和多线程的概念区别,现在记录下来我现在的想法,希望看到的朋友也能帮组