• .net 进阶学习 多线程--(1)


    • 1.多线程概念解释

      进程:计算机概念,程序在服务器运行时占据全部计算资源综总和虚拟的

      线程:计算机概念,进程在响应操作时最小单位,也包含CPU 内存 网络 硬盘IO虚拟的概念,更加看不见摸不着

      一个进程会包含多个线程;线程隶属于某个进程,进程销毁线程也就没了

      句柄:其实是个long数字,是操作系统标识应用程序

      多线程:计算机概念,一个进程有多个线程同时运行

            同步方法:发起调用,完成后才继续下一行;非常符合开发思维,有序执行;
       异步方法:发起调用,不等待完成,直接进入下一行,启动一个新线程来完成方法的计算

    • 2.多线程使用原因

      1.多个CPU的核可以并行工作,4核8线程,4CPU 这里的线程指的是模拟核

      2.CPU分片,1s的处理能力分成1000份,操作系统调度着去响应不同的任务
      从宏观角度来说,感觉就是多个任务在并发执行
      从微观角度来说,一个物理cpu同一时刻只能为一个任务服务

       并行:多核之间叫并行
      并发:CPU分片的并发

    • 3.同步方法
       #region Private Method
            /// <summary>
            /// 一个比较耗时耗资源的私有方法,为后面测试使用时调用
            /// </summary>
            /// <param name="name"></param>
            private void DoSomethingLong(string name)
            {
                Console.WriteLine($"****************DoSomethingLong Start  {name}  {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
                long lResult = 0;
                for (int i = 0; i < 1000000000; i++)
                {
                    lResult += i;
                }
                //Thread.Sleep(2000);
    
                Console.WriteLine($"****************DoSomethingLong   End  {name}  {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} {lResult}***************");
            }
            #endregion
    View Code
     #region Sync
            /// <summary>
            /// 同步方法
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnSync_Click(object sender, EventArgs e)
            {
                Console.WriteLine($"****************btnSync_Click Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
                int l = 3;
                int m = 4;
                int n = l + m;
                for (int i = 0; i < 5; i++)
                {
                    string name = string.Format($"btnSync_Click_{i}");
                    this.DoSomethingLong(name);
                }
                Console.WriteLine($"****************btnSync_Click   End {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
    
            }
            #endregion
    View Code
    • 4.异步方法:
    1. BeginInvoke :委托自身需要的参数,2个异步参数 
    //for循环需要定义一个变量  
    string name = string.Format($"btnAsync_Click_{i}");
     #region Async
            /// <summary>
            /// 异步方法
            /// 1 同步方法卡界面:主线程(UI线程)忙于计算,无暇他顾
            ///   异步多线程方法不卡界面:主线程闲置,计算任务交给子线程完成
            ///   改善用户体验,winform点击个按钮不至于卡死;
            ///   web应用发个短信通知,异步多线程去发短信;
            /// 
            /// 2 同步方法慢,只有一个线程计算
            ///   异步多线程方法快,因为5个线程并发计算
            ///   12658ms   3636ms  不到4倍   CPU密集型计算(资源受限)
            ///   10126ms    2075ms  差不多5倍,也不到5倍,Sleep(资源够用)
            ///   多线程其实是资源换性能,1 资源不是无限的  2 资源调度损耗
            ///   
            ///   一个订单表统计很耗时间,能不能多线程优化下性能?  不能!这就是一个操作,没法并行
            ///   需要查询数据库/调用接口/读硬盘文件/做数据计算,能不能多线程优化下性能? 可以,多个任务可以并行
            ///   线程不是越多越好,因为资源有限,而且调用有损耗
            ///   
            /// 3 同步方法有序进行,异步多线程无序
            ///   启动无序:线程资源是向操作系统申请的,由操作系统的调度策略决定,所以启动顺序随机
            ///   同一个任务同一个线程,执行时间也不确定,CPU分片
            ///   以上相加,结束也无序
            ///   使用多线程请一定小心,很多事儿不是相当然的,尤其是多线程操作间有顺序要求的时候,
            ///   通过延迟一点启动来控制顺序?或者预计下结束顺序?  这些都不靠谱!
            ///   
            ///   需要控制顺序,晚点分解!
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnAsync_Click(object sender, EventArgs e)
            {
                Console.WriteLine($"****************btnAsync_Click Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
                Action<string> action = this.DoSomethingLong;
    
                //action.Invoke("btnAsync_Click_1");
                //action("btnAsync_Click_1");
    
                //委托自身需要的参数+2个异步参数
                //action.BeginInvoke("btnAsync_Click_1", null, null);
    
                for (int i = 0; i < 5; i++)
                {
                    string name = string.Format($"btnAsync_Click_{i}");
                    action.BeginInvoke(name, null, null);
                }
    
                Console.WriteLine($"****************btnAsync_Click End   {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
            }
            #endregion
    View Code

       2. 回调,控制顺序:将后续动作通过回调参数传递进去,子线程完成计算后,去调用这个回调委托

     Action<string> action = this.DoSomethingLong;
    
                ////1 回调:将后续动作通过回调参数传递进去,子线程完成计算后,去调用这个回调委托
                IAsyncResult asyncResult = null;//是对异步调用操作的描述
                AsyncCallback callback = ar =>
                {
                    Console.WriteLine($"{object.ReferenceEquals(ar, asyncResult)}");
                    Console.WriteLine($"btnAsyncAdvanced_Click计算成功了。{ar.AsyncState}。{Thread.CurrentThread.ManagedThreadId.ToString("00")}");
                };
                asyncResult = action.BeginInvoke("btnAsyncAdvanced_Click", callback, "花生");
    View Code

       3. 通过IsComplate等待,控制顺序:卡界面--主线程在等待,边等待边提示

                 //////2 通过IsComplate等待,卡界面--主线程在等待,边等待边提示
                //////( Thread.Sleep(200);位置变了,少了一句99.9999)
            Action<string> action = this.DoSomethingLong;
            IAsyncResult asyncResult = null;//是对异步调用操作的描述
                AsyncCallback callback = ar =>
                {
                    Console.WriteLine($"{object.ReferenceEquals(ar, asyncResult)}");
                    Console.WriteLine($"btnAsyncAdvanced_Click计算成功了。{ar.AsyncState}。{Thread.CurrentThread.ManagedThreadId.ToString("00")}");
                };
                asyncResult = action.BeginInvoke("btnAsyncAdvanced_Click", callback, "花生");
    
    
                int i = 0;
                while (!asyncResult.IsCompleted)
                {
                    if (i < 9)
                    {
                        Console.WriteLine($"中华民族复兴完成{++i * 10}%....");
                    }
                    else
                    {
                        Console.WriteLine($"中华民族复兴完成99.999999%....");
                    }
                    Thread.Sleep(200);
                }
                Console.WriteLine("中华民族复兴已完成,沉睡的东方雄狮已觉醒!");            
    View Code

       4. WaitOne等待,即时等待  限时等待

                asyncResult.AsyncWaitHandle.WaitOne();//直接等待任务完成
                asyncResult.AsyncWaitHandle.WaitOne(-1);//一直等待任务完成
                asyncResult.AsyncWaitHandle.WaitOne(1000);//最多等待1000ms,超时就不等了
    View Code

       5. EndInvoke  即时等待,而且可以获取委托的返回值 一个异步操作只能End一次

      Action<string> action = this.DoSomethingLong;
    
                ////4 EndInvoke  即时等待,而且可以获取委托的返回值 一个异步操作只能End一次
                IAsyncResult asyncResult = null;//是对异步调用操作的描述
                AsyncCallback callback = ar =>
                {
                    Console.WriteLine($"{object.ReferenceEquals(ar, asyncResult)}");
                    Console.WriteLine($"btnAsyncAdvanced_Click计算成功了。{ar.AsyncState}。{Thread.CurrentThread.ManagedThreadId.ToString("00")}");
                };
                asyncResult = action.BeginInvoke("btnAsyncAdvanced_Click", callback, "花生");
    
                action.EndInvoke(asyncResult);//等待某次异步调用操作结束
    
                Console.WriteLine("全部计算成功了。。");
    View Code
      Func<int> func = () =>
                {
                    Thread.Sleep(2000);
                    return DateTime.Now.Hour;
                };
                int iResult = func.Invoke();//22
                IAsyncResult asyncResult = func.BeginInvoke(ar =>
                 {
                     //int iEndResultIn = func.EndInvoke(ar);
                 }, null);
                int iEndResult = func.EndInvoke(asyncResult);//22
    View Code
  • 相关阅读:
    Git 分支开发规范
    小程序技术调研
    弹性布局
    vue 自定义指令的魅力
    记一次基于 mpvue 的小程序开发及上线实战
    mpvue学习笔记-之微信小程序数据请求封装
    微信小程序开发框架 Wepy 的使用
    Hbuilder 开发微信小程序的代码高亮
    luogu3807 【模板】 卢卡斯定理
    luogu1955 [NOI2015] 程序自动分析
  • 原文地址:https://www.cnblogs.com/AlexLeeLi/p/10511985.html
Copyright © 2020-2023  润新知