游戏电视苹果数码历史美丽
投稿投诉
美丽时装
彩妆资讯
历史明星
乐活安卓
数码常识
驾车健康
苹果问答
网络发型
电视车载
室内电影
游戏科学
音乐整形

多线程和异步有什么关联和区别?如何实现异步?

  很多很多年前,有个叫DOS的操作系统。
  DOS通过一行一行命令运行程序。在同一时刻里,你只可能运行一个程序,这就是单进程系统。
  后来出现了Windows,用户可以在系统中打开多个程序并使用它们。这就是多进程系统。
  线程与进程的关系,就如同进程与系统的关系。一个系统可以存在多个进程,一个进程也可以存在多个线程。
  今天的主题与多线程的原理关系不大,因此就不在其原理上进行更多的说明和解释了。什么是单线程,什么是多线程
  还得记大约五、六年前,我去KFC和McDonalds就发现了一个有趣的区别。
  在KFC中,收银与配餐是同一人。
  顾客在点餐后,继续站在原地等待西餐,造成了KFC中常常能见到长长的队伍在排队。
  在McDonalds,这两件事是由两个不同的人负责的。
  顾客在点餐完成后,带着号离开点餐的队伍,直接去等待配餐叫号。点餐的队伍人数比KFC明显少了许多。
  对比这两种模式,你会发现KFC的模式很容易积压一长排的顾客,让他们烦于等待而最终离开。McDonalds的模式不容易产生排长队的顾客,并且可以让顾客早早的进入叫号等餐环节。
  我们把线程视作员工,把顾客视作任务,于是这两个例子就可以非常形象的解释什么单线程,什么是多线程。KFC这种模式模式就是单线程,一个任务从头至尾由一线程完成,在一个任务完成之前,不接受第二个任务。McDonalds这种模式就是多线程,将一个任务拆分成不同的阶段(部分),并交给不同的线程分别处理。什么是同步,什么是异步
  当你明白了KFC和McDonalds后,一切就很简单了。
  线程是员工,同步异步就是顾客点餐的流程了。顾客不能去一下洗手间,只能呆呆地站在那里等待配置的模式就是同步。顾客支付以后,利用等待配置的时间去一下洗手间,找个座位的模式就是异步。
  显而易见,异步可以提供更高的效率,它可以利用等待的时间去完成一些事情。
  在我们的代码中,一个顾客一边等待配置、一边做些别的事情,就是多线程了。
  因此,(单多线程)与(同异)步是密不可分的两个概念。实现异步
  在正常情况下,我们写出来的代码都是同步的,上一行代码没做完就肯定不会执行第二行。
  所以如何实现同步这个问题的答案与如何写一段代码是一样的。
  那么,我们自然而然的就把目光放在了如何实现异步,这一话题上了。
  在。Net中,我们有几种异步的实现方案:ThreadBeginInvokeTaskasyncawait
  下面,我会介绍每种方案是如何实现的Thread
  首先,如上面所提到的,异步的目标就是,先开始某个任务,然后利用等待的时间去做点别的事情。
  很明显,这里有两个线程一个负责某个任务。另一个负责别的事情,并在完成别的事情后开始等待某个任务的完成。
  利用这个思想,我们可以自己做一个异步的小例子了。某个任务的结果intresultOfSomeTask0;ThreadsomeTasknewThread(newThreadStart((){Thread。Sleep(1000);resultOfSomeTask100;}));someTask。Start();DoSomething(1);做一些别的事情DoSomething(2);做一些别的事情DoSomething(3);做一些别的事情每隔一会儿去看看【某个任务】是否完成了while(true){if(someTask。ThreadStateThreadState。Stopped)break;Thread。Sleep(1);}Assert。AreEqual(100,resultOfSomeTask);
  代码说明我们利用Thread创建一个线程,让它去完成某个任务,我们模拟该任务需要1秒钟,并会产生一个100的结果使用Thread。Start开始这个任务在someTask执行过程中,我们做作一些别的事情利用一个轮询查看someTask的状态,当完成后,我们发现已经得到了100这个结果。
  上面例子中while(true)部分,我们可以使用Thread。Join()方法来代替以达到同样的效果。某个任务的结果intresultOfSomeTask0;ThreadsomeTasknewThread(newThreadStart((){Thread。Sleep(1000);resultOfSomeTask100;}));someTask。Start();DoSomeThine(2);做一些别的事情DoSomeThine(3);做一些别的事情DoSomeThine(1);做一些别的事情产生与while(true)同样的效果当someTask完成后,才会继续进行someTask。Join();Assert。AreEqual(100,resultOfSomeTask);
  这种异步的实现方式让开发者无法只关注在逻辑本身,代码中混入了大量的与线程有关的代码。
  而且最不人性化的是,Thread要么没有参数,要么只给一个object类型的参数,最草稿的是,它无法返回结果,我们必须写一些额外的代码、逻辑去要主线程中得到子线程中的结果。
  题外话
  在实际生产环境中,我们往往使用ThreadPool来开启线程。
  毕竟每开一个线程,系统都会产生一相应的消耗来支持它。
  ThreadPool可以开启有限个的线程,并对任务排队,仅当有线程空闲时,才会继续处理任务。BeginInvoke
  BeginInvoke是Delegate上的一个成员,它与EndInvoke一起使用可以实现异步操作。BeginInvoke相当于上面例子中Thread。Start()的功能EndInvoke相当于上面例子中Thread。Join()的功能
  因为BeginInvoke是Delegate上的成员,所以我们先声明一个Delegatesummary这是一个描述了一个使用整形并返回整形的委托类型。你可以使用直接使用Funcint,int来作为委托的类型。summaryparamnameiparamreturnsreturnspublicdelegateintTaskGetIntByInt(inti);
  BeginInvoke的入参比较特别,它分为两个分部。前面的几个参数,就是委托中定义的参数后面两个参数,一个是异步任务完成时的回调,一个是可以向回调函数传入的额外参数,你可以传递任何你需要的内容至回调里,而避免了在进程内访问进程外成员的情况
  下面是一个BeginInvoke的例子这是一个耗时1秒的任务,会返回入参的平方数TaskGetIntByIntsomeTasknewTaskGetIntByInt(i{Thread。Sleep(1000);returnii;});定义一个函数,用于someTask完成时的回调AsyncCallbackcallbacknewAsyncCallback(ar{stringstatear。AsyncStateasstring;Assert。AreEqual(Hello,state);});开始平方数运算的任务callback,HelloWorld根据需求传入,你也可以传nullIAsyncResultarsomeTask。BeginInvoke(10,callback,HelloWorld);开始一些别的任务DoSomeThing(1);DoSomeThing(2);DoSomeThing(3);等待someTask的运算结果,形如Thread。Join()intresultsomeTask。EndInvoke(ar);Assert。AreEqual(100,result);
  代码说明
  首先创建委托的实例,你可以使用其它类型上的成员来构造,也可以像示例中那样直接写一个内部方法。
  接下来使用BeginInvoke开始异步调用。注意这里返回了一个IAsyncResult类型。
  你可以把这个IAsyncResult理解为你在McDonalds点好餐后的号,每个人的号都是不同的,每个顾客都可以用这个号领取你的美食。
  在代码中,每次调用BeginInvoke都会产生不同的IAsyncResult,你可以用不同的IAsyncResult去获取它们对应的结果。
  BeginInvoke的时候,你还可以指定一个回调函数,还可以指定一个变量,供回调函数使用。
  此时,someTask已经在子线程中运行了。同时,主线程继续执行了3个DoSomething()方法。
  当你需要someTask的运行结果时,你只需要调用someTask。EndInvoke(IAsyncResult)。当子线程已经完成后,调用EndInvoke你可以立即得到结果。当子线程尚未完成时,调用EndInvoke会一直等待,等到子线程执行完成后,才可以得到结果。
  题外话
  若你的异步任务是一个耗时极长的任务,在主线程使用EndInvoke会傻等很久。
  此时,你可以将EndInvoke方法在Callback内执行。
  将someTask作为回调函数的参数传入,就可以在Callback内使用EndInvoke得到结果。TaskGetIntByIntsomeTasknewTaskGetIntByInt(i{Thread。Sleep(3000);returnii;});DoSomeThing(1);DoSomeThing(2);DoSomeThing(3);AsyncCallbackcallbacknewAsyncCallback(ar{BeginInvoke的最后一位参数可以通过AsyncState取得TaskGetIntByInttask(TaskGetIntByInt)ar。AsyncState;intresulttask。EndInvoke(ar);Assert。AreEqual(100,result);});IAsyncResultarsomeTask。BeginInvoke(10,callback,someTask);
  对于一个异步任务的结果,我们往往有两种方法处理:在主线程中等待结果在子线程中处理结果
  对于一个耗时较短的任务,我们可以先利用异步将该任务放在子线程中执行。再继续在主线程中处理其它任务,最后等待异步任务的完成。这种方式就是在主线程中等待结果。
  对于一个耗时较长的任务,如果在主线程中等待会有可能对终端用户带来不好的应用体验。
  因此,我们不会在主线程中等待异步的完成。
  我们在异步任务开启后,就可以早早通知用户你的任务正在处理中。同时在子线程中,当任务完成后,你可以利用数据库等手段,将正在处理中的任务标为已完成,并通知他们。Task
  从。Net4。0开始,Task成为了实现异步的主要利器。
  Task的用法与JavaScript中的Promise非常接近。
  Task表示一个异步任务。废话不多说,我们先写一个返回Task的方法。Taskint表示这是一个返回int类型的TaskprivateTaskintAsyncPower(inti){返回一个任务使用Task。Run相当于先创建了一个Task再StartreturnTaskint。Run((){该任务会耗时1秒钟Thread。Sleep(1000);1秒钟后会返回参数的平方returnii;});}
  与之前提到的相同,我们有两种方法处理这个Task的结果:在主线程中等待结果在子线程中处理结果
  我们看看两种模式分别是如何实现的在主线程中等待结果
  直接访问Task。Result属性,就可以等待并得到异步任务的结果。vartaskAsyncPower(10);这里会等1秒intresulttask。Result;result100
  怎么样?是不是超级简单?在子线程中处理结果
  使用方法ContinueWith可以添加一个方法,在Task完成后被执行。
  这个ContinueWith和JavaScript里的Promise的then方法有着异曲同工的效果。vartaskAsyncPower(10);task。ContinueWith(t{intresultt。Result;result100});
  怎么样?是不是依然超级简单?
  就像之前说的,Task用起来就像Promise,Promise最大的特点就是可以用一步一步then下去。。get(someurl)。then(rltfoo(rlt))。then(rltbar(rlt));
  Task的ContinueWith也支持这样的编写方法:vartaskAsyncPowe(10);task。ContinueWith(t{somecodehere})。ContinueWith(t{somecodehere})。CondinueWith(t{somecodehere});asyncawait
  这个。Net4。5加入的关键字,让异步代码写起来和同步代码没什么区别了。
  我们先看看下面的同步代码intPower(inti){returnii;}voidMain(){intresultPower(10);Console。WriteLine(result);100Console。ReadLine();}
  把上面的代码改成异步代码,只需要几个小小的改动:将Power的返回值改为Task修改返回结果,使用Task。Run包装返回的结果为调用Power的代码前加上await关键字为有await关键字的方法加上async关键字
  新的代码如下TaskintPower(inti){returnTaskint。Run((){Thread。Sleep(100);模拟耗时returnii;});}asyncvoidMain(){Console。WriteLine(Hello);intresultawaitPower(10);Console。WriteLine(result);100Console。ReadLine();}
  运行一下,发现没什么区别。
  如果你向控制台输出线程ID的话,你会发现Console。WriteLine(Hello)和Console。WriteLine(result)并不工作在同一个线程同。
  为什么会有这样的效果?
  因为编译器,你会发现,和之前的异步实现不同,async和await不是某个封装了复杂逻辑的类型,而是两个关键字。
  关键字的意义就是编译过程。
  在编译时,遇到async就会知道这是一个存在着异步的方法,编译器向这个类型添加一些额外的成员来支持await操作。
  当遇到await关键字时,编译器会从当前行截断,并向后面的代码编译到Task。ContinueWith中去。
  这样一来,看似同步的代码,经编译后,就会一拆为二。
  前部分运行在主线程中,后部分运行在子线程中,分割点就是await所在的代码行。慎用异步
  几种在。Net平台中使用异步的方法都介绍完了,希望大家能够对异步编程有了一定的了解和认识。
  但是,在实际生产中,依赖要慎用异步。
  异步在带来性能提高的同时,还会带来一些更复杂的问题:线程安全
  线程间的切换并不是有着类似事务的特征,它无法保证两个线程对同一资源的读写的完整性。
  而且大部分情况下,一个线程操作完,就会被挂机执行另一个线程,所以对于多个线程访问同一资源,需要考虑线程安全的问题。
  换句话说,就是保证一个线程在执行一个最小操作时,另一个线程不允许操作该对象。调试难
  异步的本质就是多线程,当你尝试用断点调试代码时,由于两个线程都在你的代码中运行,因此常常出现从这个线程的断点进入另一个线程的断点的情景。
  需要依赖IDE中更多的工具和设置,才能解决上述的问题。不统一的上下文
  异步代码往往在子线程中运行。
  子线程很可能会使用在主线程中已经施放的资源。
  比如using(varconnnewSqlConnection(。。。。。。。。)){conn。Open();假定一个根据用户名查询用户ID的方法TastinttaskUserService。AsyncGetUserId(conn,Admin);task。ContinueWith(t{此时的conn已经被主线程释放了UserService。DoSomethingWithConn(conn);});}
  你需要使用一些额外的代码来解决这些问题。并且这些代码不一定具备通用性,往往要具体问题具体分析。
  因此在实际任务中,到底选择同步还是异步要视具体情况而定。
  今天本文介绍了几种实现异步的方法,不能说它们之间谁比谁更好一点,各有优劣。
  篇幅原因,将不再对几种方案进行对比,会在以后的文章中详细地介绍各自优劣。

抖音无法保存视频怎么办?分享5招华为手机录屏方法,快学起来大家平时也喜欢刷抖音吧!看短视频的时候是不是也想保存到手机中分享给朋友看看呢?不过有时候因为视频作者设置了权限,我们无法将其进行保存。这时候可以采取录屏的方法将其保存下来,那录……网购为何越来越放心?看看唯品会质检链有多复杂就明白了自疫情缓解以来,线上购物依旧保持着十分迅猛的的发展态势,消费者手指轻点就能享受全球好物,买到心仪的超值正品。像京东、天猫、唯品会等电商平台,为抢占消费者,更是通过多种方法与海内……高德地图这4个神仙级功能,很多司机都不知道,开车出行太好用了导航地图已经是我们日常生活中必不可少的手机软件,除过正常的导航、定位导航功能,其实还有很多实用的功能。生活的乐趣在于发现,今天我又发现了高德导航4个神仙级功能,特别的实用。大家……智能双刷全面吸拖洗一步到位石头洗地机U10评测打扫清洁是千千万万个家庭每天都在发生的事情,人类最早使用的清洁工具从树枝、竹条到鸡毛掸子和扫把,慢慢地再随着棉麻的大量普及,以及地面材质的变化,开始出现了水洗清洁的需求,于是人……老用户真的不如狗?为什么巨头在不停地推广专属流量卡?移动互联网发展到下半场之后的一个标志现象是,互联网企业获取新用户,也就是买流量的价格越来越高,一个IOS游戏的注册用户,可能要花费企业三四十乃至四五十的成本来获取;而在移动设备……6G要来了!?这些新材料将大有所为据了解,6G将可能使用太赫兹(THz)频段,其传输能力可能比5G提升100倍,网络延迟也可能从毫秒降到微秒级。具体到太赫兹(Terahertz,THz)本身来说,它是一个……第1000万台发动机下线长城汽车蜂巢动力引领千万时代6月17日,长城汽车蜂巢动力第1000万台发动机在蜂巢易创扬中产业园区下线。至此,长城汽车蜂巢动力成为中国汽车品牌首家生产销售发动机达到一千万台量级的企业。中国内燃机工业协会秘……最爱的7款入门级香水,小众不易撞!颜值还超高不知道你是否跟我一样,生活的部分快乐来源就是买到自己喜欢又好闻的香水就连每天的早起、夏日出门都开始变得有动力了。所以今天就来给小可爱们推荐7款女生入门级香水!小众高……Win10系统自带的上帝模式。知道这个的都是高手为什么说知道的是高手?因为知道这个的,不是专业维护电脑技术人员就是程序员之类的。人数少之又少!知道这个模式的一定是对电脑知识的热爱。〔祈祷〕〔祈祷〕〔祈祷〕下面教大家如何……中国在机器人方面的技术实力相当强大在军工和航天等特殊领域的机器人技术和设备,我们并不落后,但是工业机器人技术和设备远远落后于欧洲和日本。中国和美国都属于机器人技术不差,但是产业化很差的情况。日前,日经中文……vivoS12Pro上手实测!高颜值之下隐藏着强劲的性能在很多人的印象中,vivoS系列最大的优势就在于拥有超高的外观颜值以及强大的影像实力,不过此前新上线的vivoS12系列却发生了很大的变化。为了满足当下年轻人对于强悍性能以及出……加密货币的未来究竟属于圈子还是大众?文毕舸加密货币的第二春热度不减,继去年比特币疯涨之后,美国加密货币平台Coinbase上市,首日市值达到600多亿美元,这也进一步助推加密货币市场迎集体狂欢。Wind数据……
2018年动漫女神排行榜最新动漫十大人气美女排行榜2018年动漫女神排行榜:最新动漫十大人气美女排行榜凌波最高,长门最萌,投身于二次元的男性生命体们心中都有着属于各自的人气偶像,有人偏爱御姐,有人钟情三无。正所谓你方唱罢……AKB48最性感胴体美女akb48最美成员名字TOP10AKB48最性感胴体美女,akb48最美成员名字。AKB48名字取自东京的秋叶原地区(简称Akiba),AKB48是日本著名的大型女子偶像组合。总人数已超过500人,其中可谓是……千与千寻的恐怖真相那些你忽略又有重大暗示的细节《千与千寻》是一部闻名全球的经典动画片,不得不承认确实好看,这部动画片虽然是一部以恐怖背景为主题的动画片。可是很多人都在其中看到了爱与希望,单纯与正直,就像经典的东西远远不止你……很难想象这是一条千元塞,水月雨KATO很难想象这是一条千元塞,水月雨KATO有线耳机经过这几年的发展,尤其在具有外部明显不利因素,例如无线化趋势等的影响之下,越来越多的厂家开始进入行业发展的价格战阶段,而本身……花城为什么叫三郎花城死灵蝶怎么得来的相信很多小伙伴都在看过《天官赐福》这部动漫和这部小说,无论是看过动漫,还是小说,甚至是听朋友讲的,大家可能都有一个疑惑那就是花城为什么叫三郎呢?下面就和小编一起来看看吧。……星游记之风暴法米拉简介五色眼都有谁及是什么能力星游记之风暴法米拉简介:五色眼都有谁及是什么能力星游记之风暴法米拉简介:去年7月中国首部网络动画电影《星游记之风暴法米拉》在京举行定档发布会,并曝光首支预告。作为中国首部……闪电侠和快银谁更快正义联盟和复仇者联盟还真的打过一架闪电侠和快银谁更快:正义联盟和复仇者联盟还真的打过一架超级英雄电影《正义联盟》已经上映一周左右了,在这部DC电影里,闪电侠给我们留下了深刻的印象。提到闪电侠,他拥有……win7电脑出现宽带连接错误711的解决方法说到宽带连接就是拨号上网在没有路由器的时代,还是非常重要的,这个习惯很多深度技术的用户依然保持着。这不有一位win7专业版系统用户就遇到了电脑联网时出现宽带连接错误711的问题……机智的恋爱什么时候播出,机智的恋爱嘉宾名单机智的恋爱你说出来很多人不清楚,可机智的恋爱综艺是什么时候播出,很多网友就想去了解一下有关的故事,看机智的恋爱提早公布海报,加上相关的预告,好让观众提前预览,但有的网友就不清楚……拳力以赴的我们播出时间,拳力以赴的我们嘉宾名单拳力以赴的我们说出来很多人不清楚,可拳力以赴的我们综艺节目所安排的播出时间,很多网友就想去了解一下有关的故事,看拳力以赴的我们提早宣布海报和相关的情节,但有的网友就不清楚拳力以……智能数码的应用越来越广泛,一款新颖的管家设备分享给伙伴们!科技的迅猛发展让现代人的工作生活节奏越来越快,大量的时间和精力都被投入到繁忙的工作当中,从而疏忽了对家的照看,在工作时多了一份对家牵挂和心里不安。为了提高人类的生活质量,实现在……宫崎骏十大经典动漫电影让你身临其境宫崎骏的童话世界宫崎骏的动漫电影一直都是好评连连。宫崎骏的动漫电影不仅是剧情好,让观众看过之后有深思,而且他的电影的画面一直也是非常完美的,有非常高的代入感,让人有身临其境的感觉。下面我们来了……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网