zoukankan      html  css  js  c++  java
  • 异步和多线程,委托异步调用,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)
                    ///{
                    ///     锁住啦
                    ///}
  • 相关阅读:
    蓝桥杯Java真题解析
    第十届蓝桥杯JavaB组总结
    Java框架相关
    认识JDBC
    Lua中 MinXmlHttpRequest如何发送post方式数据
    ios 的EditBox点击空白处不隐藏的解决方案
    AssetsManager 在ios更新失败解决方案
    Cocos Studio编辑器运行日志路径
    华为 进入和退出Fastboot、eRecovery和Recovery升级模式
    cocos lua 加密方案
  • 原文地址:https://www.cnblogs.com/AnkerZhang/p/7195315.html
Copyright © 2011-2022 走看看