NET多线程进阶

本章知识点:
1 进程-线程-多线程,同步和异步
2 委托启动异步调用
3 多线程特点:不卡主线程、速度快、无序性
4 异步的回调和状态参数
5 异步等待三种方式
6 异步返回值
一,基础知识
  • 进程:计算机虚拟概念,程序与在服务器运行时占据全部计算资源综合
  • 线程:计算机虚拟概念,进程在相应操作时最小单位,包含该进程CPU,内存,网络,硬盘(一个进程有个多个线程,线程隶属于进程,进程一旦销毁该线程也会被销毁)
  • 句柄:其实是个long数字,是操作系统标识应用程序(id)
  • 多线程:计算机概念,一个进程有多个线程同时运行
  • 为什么可以多线程呢??
    (1)多个CPU的核可以并行工作(如:4核8线程。这里的线程指的是模拟核)
    (2)CPU分片,1s的处理能力分成1000份,操作系统调度着去响应不同的任务【 从宏观角度来说,感觉就是多个任务在并发执行,从微观角度来说,一个物理cpu同一时刻只能为一个任务服务】
  • 并行:多和之间叫并行
  • 并发:CPU分片的并发
  • 同步方法:发起调用,完成后才继续下一行,非常符合开发思维,有序执行;(诚心诚意的请人吃饭,邀请Nick,Nick要忙一会儿,等着Nick完成后,再一起去吃饭)
  • 异步方法:发起调用,不等待完成,直接进入下一行,启动一个新线程来完成方法的计算;( 客气一下的请人吃饭,邀请亡五,亡五要忙一会儿,你忙着我去找Nick吃饭了)
  • 同步方法和异步方法的区别和联系?
    (1)同步方法卡界面:主线程(UI线程)忙于计算,无暇他顾
    (2)异步多线程方法不卡界面:主线程闲置,计算任务交给子线程完成(应用:改善用户体验,winform点击个按钮不至于卡死;【web应用发个短信通知,异步多线程去发短信】)
    (3)同步方法慢,只有一个线程计算,
    (4)异步多线程方法快,因为5个线程并发计算(多线程其实是资源换性能,用更多的资源换更少的时间,但是,资源不是无限的,而且资源调用是有损耗的,所以线程不是越多越好)
  一个订单表统计很耗时间,能不能多线程优化下性能?  不能!这就是一个操作,没法并行
  需要查询数据库/调用接口/读硬盘文件/做数据计算,能不能多线程优化下性能? 可以,多个任务可以并行

(5)同步方法有序进行,异步多线程无序进行 (启动无序:线程资源是向操作系统申请的,由操作系统的调度策略决定,所以启动顺序随机,同一个任务同一个线程,执行时间也不确定,CPU分片,以上相加,结束也无序)

使用多线程请一定小心,很多事儿不是相当然的,尤其是多线程操作间有顺序要求的时候,通过延迟一点启动来控制顺序?或者预计下结束顺序?  这些都不靠谱!
二,BeginInvoke的回调
场景:使用多线程调用方法,如何在该方法调用完成后,打印日志~
		/// <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 < 1_000_000_000; i++)
            {
                lResult += i;
            }
            Console.WriteLine($"****************DoSomethingLong   End  {name}  {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} {lResult}***************");
        }


		/// <summary>
        /// 测试回调
        /// </summary>
        /// <param name="name"></param>
        private void btnAsyncAdvanced_Click()
        {
        
     	   {
			   Action<string> action = this.DoSomethingLong;
		 		//1 回调:将后续动作通过回调参数传递进去,子线程完成计算后,去调用这个回调委托
		        IAsyncResult asyncResult = null;//是对异步调用操作的描述
		        AsyncCallback callback = ar =>
		        {
		                Console.WriteLine($"{object.ReferenceEquals(ar, asyncResult)}"); //判断 ar 和 asyncResult是否是同一个对象
		                Console.WriteLine($"btnAsyncAdvanced_Click计算成功了。{ar.AsyncState}。{Thread.CurrentThread.ManagedThreadId.ToString("00")}");
		        };//ar.AsyncState :接受参数
		        asyncResult = action.BeginInvoke("btnAsyncAdvanced_Click", callback, "花生"); //BeginInvoke(方法名,回调函数,回调参数)

			}
            //2 通过IsComplate等待,卡界面--主线程在等待,边等待边提示
			{
	            int i = 0;
	            while (!asyncResult.IsCompleted)
	            {
	                if (i < 9)
	                {
	                    Console.WriteLine($"中华民族复兴完成{++i * 10}%....");
	                }
	                else
	                {
	                    Console.WriteLine($"中华民族复兴完成99.999999%....");
	                }
	                Thread.Sleep(200);
	            }
	            Console.WriteLine("中华民族复兴已完成,沉睡的东方雄狮已觉醒!");
			}
			{
	            //3 WaitOne等待,即时等待 限时等待
	            asyncResult.AsyncWaitHandle.WaitOne();//直接等待任务完成
	            asyncResult.AsyncWaitHandle.WaitOne(-1);//一直等待任务完成
	            asyncResult.AsyncWaitHandle.WaitOne(1000);//最多等待1000ms,超时就不等了
	            //4 EndInvoke 即时等待, 而且可以获取委托的返回值 一个异步操作只能End一次		
	            action.EndInvoke(asyncResult);//等待某次异步调用操作结束
	            Console.WriteLine("全部计算成功了。。");
		   }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值