异步多线程(一)

进程

计算机概念,程序在服务器运行时占据全部计算机资源总和,虚拟的。包含CPU、内存、网络、硬盘

MSDN:

当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源。

而一个进程又是由多个线程所组成的。

线程

计算机概念,进程在响应操作时最小单位,也包含CPU、内存、网络、硬盘

MSDN:

线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数。

多线程

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

MSDN:

多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。

为什么可以多线程

多个CPU的核可以并行工作,

4核8线程,这里的线程指的是模拟核

CPU分片

1s的处理能力分成1000份,操作系统调度着去响应不同的任务

从宏观角度来说,就是多个任务在并发执行

从微观角度来说,一个物理cpu同一时刻只能为一个任务服务

并行:多核之间叫并行

并发:CPU分片的并发

多线程其实是资源换性能,1 资源不是无限的  2 资源调度损耗

多线程的好处: 

可以提高CPU的利用率。在多线程程序中,一个线程必须等待的时候,CPU可以 运行其它的线程而不是等待,这样就大大提高了程序的效率。

多线程的不利之处

线程也是程序,所以线程需要占用内存,线程越多占用内存也越多; 多线程需要协调和管理,所以需要CPU时间跟踪线程;

线程之间对共享资源的访问会相互影响,必须解决竞用共享资源的问题;线程太多会导致控制太复杂,最终可能造成很多Bug;

同步与异步

同步:

发起调用,完成后才继续下一行;非常符合开发思维,有序执行;

异步:

发起调用,不等待完成,直接进入下一行,启动一个新线程来完成方法的计算

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

同步方法慢,异步多线程方法快

  同步:只有一个线程计算 异步:因为多个线程并发计算

同步方法卡界面,异步多线程方法不卡界面

  同步方法:            主线程(UI线程)忙于计算,无暇他顾
  异步多线程方法: 异步多线程方法不卡界面:主线程闲置,计算任务交给子线程完成

同步代码示例:

        /// <summary>
        /// 同步方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {

            Console.WriteLine($"button1_Click*****Start{Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString()}");
            for (int i = 0; i < 5; i++)
            {
                string name = string.Format($"button1_Click{i}");
                this.DoSomethingLong(name);
            }

            Console.WriteLine($"button1_Click*****End{Thread.CurrentThread.ManagedThreadId} {DateTime.Now.ToString()}");
        }

程序执行完成,我们可以清晰的看到,同步方法是有序的执行

异步代码示例:

        /// <summary>
        /// 异步多线程
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click_1(object sender, EventArgs e)
        {
            Console.WriteLine($"****************button2_Click Start " +
                $"{Thread.CurrentThread.ManagedThreadId.ToString("00")} " +
                $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");

            Action<string> action = this.DoSomethingLong;

            for (int i = 0; i < 5; i++)
            {
                string name = string.Format($"button2_Click_1{i}");
                action.BeginInvoke("button2_Click", null, null);//委托异步多线程调用

            }

            Console.WriteLine($"****************button2_Click End " +
                $"{Thread.CurrentThread.ManagedThreadId.ToString("00")} " +
                $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");

        }

程序运行之后,我们会发现运行的结果是无序的

回调

将后续动作通过回调参数传递进去,子线程完成计算后,去调用这个回调委托。

代码示例:

        /// <summary>
        /// 异步多线程回调、等待
        /// Action
        /// Func
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)
        {
            #region  回调
            {
                Action<string> action = this.DoSomethingLong;
                IAsyncResult asyncResult = null;//是对异步调用操作的描述
                AsyncCallback callback = mm =>
                {//这里是一个委托

                    Console.WriteLine($"{object.ReferenceEquals(mm, asyncResult)}");
                    Console.WriteLine($"button3_Click计算成功了。{mm.AsyncState}。{Thread.CurrentThread.ManagedThreadId.ToString("00")}");

                };

                //回调

                action.BeginInvoke("button3_Click", callback, "嘿嘿");//先执行action然后回调 callback委托
            }
            #endregion

        }

异步等待的三种方式:

IsComplate等待

通过IsComplate等待,主线程在等待,边等待边提示

            #region IsComplate等待
            {
                Action<string> action = this.DoSomethingLong;
                IAsyncResult asyncResult = null;//是对异步调用操作的描述
                AsyncCallback callback = mm =>
                {
                    Console.WriteLine($"{object.ReferenceEquals(mm, asyncResult)}");
                    Console.WriteLine($"button3_Click计算成功了。{mm.AsyncState}。{Thread.CurrentThread.ManagedThreadId.ToString("00")}");
                };
                //回调
                asyncResult= action.BeginInvoke("button3_Click", callback, "嘿嘿");//先执行action然后回调 callback委托
                int i = 0;
                while (!asyncResult.IsCompleted)
                {
                    Thread.Sleep(200);
                    if (i < 2)
                    {
                        Console.WriteLine($"正在充电{++i * 10}%....");

                    } else{
                        Console.WriteLine($"充电完成完成99.999999%....");
                    }

                }
                Console.WriteLine("充电已完成,尽情的使用手机吧!");

            }

            #endregion

程序执行完成的结果

注意:根据调用,首先执行DoSomethingLong 方法,因为DoSomethingLong方法里有密集操作,所以程序会边等待边执行while里的判断语句以及方法体

此时DoSomethingLong里的密集操作已执行完毕,接着执行callback里的方法

WaitOne等待

WaitOne等待,即时等待  限时等待

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

EndInvoke等待

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

            #region EndInvoke
            Func<int> func = ()=>
            {
                Thread.Sleep(2000);
                return DateTime.Now.Hour;

            };

            int Result = func.Invoke();

            IAsyncResult asyncResult = func.BeginInvoke(ar=> {
                //在方法里拿到结果
                // int IResult = func.EndInvoke(ar);
                //对于每个异步操作,只能调用一次EndInvoke
            }, null);
            //在方法外得到结果
            int EndResult = func.EndInvoke(asyncResult);
            #endregion

原文地址:https://www.cnblogs.com/JohnTang/p/10981424.html

时间: 2024-08-28 19:07:17

异步多线程(一)的相关文章

异步多线程

UI只能在主线程中完成更新,在子线程中更新UI报错如下 Only the original thread that created a view hierarchy can touch its views. 但是,在主线程中完成耗时操作容易引起使用体验不佳,进程卡顿问题,为了解决此问题引入异步多线程

.NET 异步多线程,Thread,ThreadPool,Task,Parallel

今天记录一下异步多线程的进阶历史,以及简单的使用方法 主要还是以Task,Parallel为主,毕竟用的比较多的现在就是这些了,再往前去的,除非是老项目,不然真的应该是挺少了,大概有个概念,就当了解一下进化史了 1:委托异步多线程,所有的异步都是基于委托来实现的 #region 委托异步多线程 { //委托异步多线程 Stopwatch watch = new Stopwatch(); watch.Start(); Console.WriteLine($"开始执行了,{DateTime.Now.

PHP开启异步多线程执行脚本

场景要求 客户端调用服务器a.php接口,需要执行一个长达5s-20s不等的耗资源操作,但是客户端响应请求时间为5秒(微信公众账号服务器请求响应超时时间),5s以上无回复即断开连接. 解决设想 客户端调用a.php之后,a.php执行异步多线程操作调用b.php,a.php调用成功后即刻反馈给客户端回执,b.php自动执行耗资源操作. PHP没有真正实现多线程操作的方法.所以需要通过其它手段来进行模拟多线程. 方案一 利用CURL非阻塞调用b.php,实现过程可以参考http://blog.cs

php异步多线程swoole用法实例

摘要:本文实例讲述了php异步多线程swoole用法.分享给大家供大家参考.具体分析如下:swoole重新定义PHP语言的高性能网络通信框架,提供了PHP语言的异步多线程服务,下面的实例就可以证实这一功能.一般来说,Swoole提供了PHP语言的异步多线程服务器,异步TCP/UDP网络客户端,异步MySQL,数据库连接池,AsyncTask,消息队列,毫秒定时器,异步文件读写,异步DNS查询.swoole 本文实例讲述了php异步多线程swoole用法.分享给大家供大家参考.具体分析如下: sw

异步多线程C/S框架gko_pool

曾经在上家公司做了一个内网P2P的传输工具名曰gingko当时太菜了,网络部分写的很差,各种阻塞式网络通信后来离职把memcached的代码研究了一下,感觉里面的网络模型非常先进我就把memcached的网络部分抽取出来和gingko做了结合,写成了一个网络框架叫gko_pool 大致特性是: 完全异步化(包括DNS解析) 可以listen一个端口当server,也可以主动发起连接写client worker是对等的多线程 内置一个简单的"内存池" 看代码发现memcached状态机有

并发 并行 同步 异步 多线程的区别

1. 并发:在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行.其中两种并发关系分别是同步和互斥2. 互斥:进程间相互排斥的使用临界资源的现象,就叫互斥.3. 同步:进程之间的关系不是相互排斥临界资源的关系,而是相互依赖的关系.进一步的说明:就是前一个进程的输出作为后一个进程的输入,当第一个进程没有输出时第二个进程必须等待.具有同步关系的一组并发进程相互发送的信息称为消息或事件.其中并发又有伪并发和真并发,伪并发是指单核处理器的并发,真并

并发 并行 同步 异步 多线程的区别 (转)

1. 并发:在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行.其中两种并发关系分别是同步和互斥 2. 互斥:进程间相互排斥的使用临界资源的现象,就叫互斥. 3. 同步:进程之间的关系不是相互排斥临界资源的关系,而是相互依赖的关系.进一步的说明:就是前一个进程的输出作为后一个进程的输入,当第一个进程没有输出时第二个进程必须等待.具有同步关系的一组并发进程相互发送的信息称为消息或事件. 其中并发又有伪并发和真并发,伪并发是指单核处理器的并发

浅入了解GCD 并发 并行 同步 异步 多线程

 什么是 GCD?! GCD就是一个函数库(废话) 用来压榨系统的资源,解决多线程处理中一些问题的库(知道这个就够了,很多电影角色都是因为知道太多死得很惨!!!!!) 1.并发与并行 Concurrency vs Parallelism  单核设备:先运行一个线程,执行一个上下文切换.这通常切换很快以致给我们有并发执行地错觉.也就是说在一秒钟内吃了饭也拉了屎,可是每半秒中只能做一件事情(吃饭或拉屎)但是给人的感觉好像是同时进行的.这是单核逻辑模拟出两个线程的假象如下图Concurrency所示:

并发 并行 同步 异步 多线程 阻塞 非阻塞的区别

1. 并发(concurrency):在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行.其中两种并发关系分别是同步和互斥 互斥:进程间相互排斥的使用临界资源的现象,就叫互斥. 同步(synchronous):进程之间的关系不是相互排斥临界资源的关系,而是相互依赖的关系.进一步的说明:就是前一个进程的输出作为后一个进程的输入,当第一个进程没有输出时第二个进程必须等待.具有同步关系的一组并发进程相互发送的信息称为消息或事件. 其中并发又有伪