:first-child{margin-top:0!important}.markdown-body>:last-child{margin-bottom:0!important}.markdown-body a:not([href]){color:inherit;text-decoration:none}.markdown-body .anchor{float:left;padding-right:4px;margin-left:-20px;line-height:1}.markdown-body .anchor:focus{outline:0}.markdown-body blockquote,.markdown-body dl,.markdown-body ol,.markdown-body p,.markdown-body pre,.markdown-body table,.markdown-body ul{margin-top:0;margin-bottom:16px}.markdown-body hr{overflow:hidden;background:#e1e4e8;height:.25em;padding:0;margin:24px 0;border:0}.markdown-body blockquote{padding:0 1em;color:#6a737d;border-left:.25em solid #dfe2e5}.markdown-body h1,.markdown-body h2{padding-bottom:.3em;border-bottom:1px solid #eaecef}.markdown-body blockquote>:first-child{margin-top:0}.markdown-body blockquote>:last-child{margin-bottom:0}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{margin-top:24px;margin-bottom:16px;font-weight:600;line-height:1.25}.markdown-body h1 .octicon-link,.markdown-body h2 .octicon-link,.markdown-body h3 .octicon-link,.markdown-body h4 .octicon-link,.markdown-body h5 .octicon-link,.markdown-body h6 .octicon-link{color:#1b1f23;vertical-align:middle;visibility:hidden}.markdown-body h1:hover .anchor,.markdown-body h2:hover .anchor,.markdown-body h3:hover .anchor,.markdown-body h4:hover .anchor,.markdown-body h5:hover .anchor,.markdown-body h6:hover .anchor{text-decoration:none}.markdown-body h1:hover .anchor .octicon-link,.markdown-body h2:hover .anchor .octicon-link,.markdown-body h3:hover .anchor .octicon-link,.markdown-body h4:hover .anchor .octicon-link,.markdown-body h5:hover .anchor .octicon-link,.markdown-body h6:hover .anchor .octicon-link{visibility:visible}.markdown-body h6{color:#6a737d}.markdown-body ol,.markdown-body ul{padding-left:2em}.markdown-body ol ol,.markdown-body ol ul,.markdown-body ul ol,.markdown-body ul ul{margin-top:0;margin-bottom:0}.markdown-body li>p{margin-top:16px}.markdown-body li+li{margin-top:.25em}.markdown-body dl{padding:0}.markdown-body dl dt{padding:0;margin-top:16px;font-size:1em;font-style:italic;font-weight:600}.markdown-body dl dd{padding:0 16px;margin-bottom:16px}.markdown-body table{border-spacing:0;border-collapse:collapse;display:block;width:100%;overflow:auto}.markdown-body table th{font-weight:600}.markdown-body table td,.markdown-body table th{padding:6px 13px;border:1px solid #dfe2e5}.markdown-body table tr{background-color:#fff;border-top:1px solid #c6cbd1}.markdown-body table tr:nth-child(2n){background-color:#f6f8fa}.markdown-body img{max-width:100%;box-sizing:content-box;background-color:#fff}.markdown-body code{padding:.2em 0;margin:0;font-size:85%;background-color:rgba(27,31,35,.05);border-radius:3px}.markdown-body code::after,.markdown-body code::before{letter-spacing:-.2em;content:"\00a0"}.markdown-body pre>code{padding:0;margin:0;font-size:100%;word-break:normal;white-space:pre;background:0 0;border:0}.markdown-body .highlight{margin-bottom:16px}.markdown-body .highlight pre{margin-bottom:0;word-break:normal}.markdown-body .highlight pre,.markdown-body pre{padding:16px;overflow:auto;font-size:85%;line-height:1.45;background-color:#f6f8fa;border-radius:3px}.markdown-body pre code{display:inline;max-width:auto;padding:0;margin:0;overflow:visible;line-height:inherit;word-wrap:normal;background-color:transparent;border:0}.markdown-body pre code::after,.markdown-body pre code::before{content:normal}.markdown-body .full-commit .btn-outline:not(:disabled):hover{color:#005cc5;border-color:#005cc5}.markdown-body kbd{display:inline-block;padding:3px 5px;font:11px SFMono-Regular,Consolas,"Liberation Mono",Menlo,Courier,monospace;line-height:10px;color:#444d56;vertical-align:middle;background-color:#fcfcfc;border:1px solid #c6cbd1;border-bottom-color:#959da5;border-radius:3px;box-shadow:inset 0 -1px 0 #959da5}.node text,.noteText,div.mermaidTooltip{font-family:'trebuchet ms',verdana,arial}.markdown-body :checked+.radio-label{position:relative;z-index:1;border-color:#0366d6}.markdown-body .task-list-item+.task-list-item{margin-top:3px}.markdown-body .task-list-item input{margin:0 .2em .25em -1.6em;vertical-align:middle}.markdown-body hr{border-bottom-color:#eee}.hljs{display:block;overflow-x:auto;padding:.5em;color:#333;background:#f8f8f8;-webkit-text-size-adjust:none}.diff .hljs-header,.hljs-comment{color:#998;font-style:italic}.css .rule .hljs-keyword,.hljs-keyword,.hljs-request,.hljs-status,.hljs-subst,.hljs-winutils,.nginx .hljs-title{color:#333;font-weight:700}.hljs-hexcolor,.hljs-number,.ruby .hljs-constant{color:teal}.hljs-doctag,.hljs-string,.hljs-tag .hljs-value,.tex .hljs-formula{color:#d14}.hljs-id,.hljs-title,.scss .hljs-preprocessor{color:#900;font-weight:700}.hljs-list .hljs-keyword,.hljs-subst{font-weight:400}.hljs-class .hljs-title,.hljs-type,.tex .hljs-command,.vhdl .hljs-literal{color:#458;font-weight:700}.django .hljs-tag .hljs-keyword,.hljs-rule .hljs-property,.hljs-tag,.hljs-tag .hljs-title{color:navy;font-weight:400}.hljs-attribute,.hljs-name,.hljs-variable,.lisp .hljs-body{color:teal}.hljs-regexp{color:#009926}.clojure .hljs-keyword,.hljs-prompt,.hljs-symbol,.lisp .hljs-keyword,.ruby .hljs-symbol .hljs-string,.scheme .hljs-keyword,.tex .hljs-special{color:#990073}.hljs-built_in{color:#0086b3}.hljs-cdata,.hljs-doctype,.hljs-pi,.hljs-pragma,.hljs-preprocessor,.hljs-shebang{color:#999;font-weight:700}.hljs-deletion{background:#fdd}.hljs-addition{background:#dfd}.diff .hljs-change{background:#0086b3}.hljs-chunk{color:#aaa}.mermaid .label{color:#333}.node circle,.node ellipse,.node polygon,.node rect{fill:#ECECFF;stroke:#CCF;stroke-width:1px}.edgePath .path{stroke:#333}.edgeLabel{background-color:#e8e8e8}.cluster rect{fill:#ffffde!important;rx:4!important;stroke:#aa3!important;stroke-width:1px!important}.cluster text{fill:#333}.actor{stroke:#CCF;fill:#ECECFF}text.actor{fill:#000;stroke:none}.actor-line{stroke:grey}.messageLine0,.messageLine1{stroke-width:1.5;stroke-dasharray:"2 2";stroke:#333}#arrowhead{fill:#333}#crosshead path{fill:#333!important;stroke:#333!important}.messageText{fill:#333;stroke:none}.labelBox{stroke:#CCF;fill:#ECECFF}.labelText,.loopText{fill:#000;stroke:none}.loopLine{stroke-width:2;stroke-dasharray:"2 2";stroke:#CCF}.note{stroke:#aa3;fill:#fff5ad}.noteText{fill:#000;stroke:none;font-size:14px}.section{stroke:none;opacity:.2}.section0{fill:rgba(102,102,255,.49)}.section2{fill:#fff400}.section1,.section3{fill:#fff;opacity:.2}.sectionTitle0,.sectionTitle1,.sectionTitle2,.sectionTitle3{fill:#333}.sectionTitle{text-anchor:start;font-size:11px;text-height:14px}.grid .tick{stroke:#d3d3d3;opacity:.3;shape-rendering:crispEdges}.grid path{stroke-width:0}.today{fill:none;stroke:red;stroke-width:2px}.task{stroke-width:2}.taskText{text-anchor:middle;font-size:11px}.taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px}.taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}.taskText0,.taskText1,.taskText2,.taskText3{fill:#fff}.task0,.task1,.task2,.task3{fill:#8a90dd;stroke:#534fbc}.taskTextOutside0,.taskTextOutside1,.taskTextOutside2,.taskTextOutside3{fill:#000}.active0,.active1,.active2,.active3{fill:#bfc7ff;stroke:#534fbc}.activeText0,.activeText1,.activeText2,.activeText3{fill:#000!important}.done0,.done1,.done2,.done3{stroke:grey;fill:#d3d3d3;stroke-width:2}.doneText0,.doneText1,.doneText2,.doneText3{fill:#000!important}.crit0,.crit1,.crit2,.crit3{stroke:#f88;fill:red;stroke-width:2}.activeCrit0,.activeCrit1,.activeCrit2,.activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}.doneCrit0,.doneCrit1,.doneCrit2,.doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}.activeCritText0,.activeCritText1,.activeCritText2,.activeCritText3,.doneCritText0,.doneCritText1,.doneCritText2,.doneCritText3{fill:#000!important}.titleText{text-anchor:middle;font-size:18px;fill:#000}.node text{font-size:14px}div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}body{margin:0;padding:0}.markdown-body{min-width:256px;max-width:978px;margin:0 auto;padding:20px;font-size:14px}.markdown-body h1{font-size:2.25em}.markdown-body h2{font-size:1.75em}.markdown-body h3{font-size:1.5em}.markdown-body h4{font-size:1.25em}.markdown-body h5,.markdown-body h6{font-size:1em}div.mermaid{text-align:center}hr.footnotes-sep{margin:64px 0 32px;height:1px}.footnotes{font-size:90%;padding-left:16px}li.footnote-item>p{margin:8px 0}.danger,.info,.success,.warning{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.danger>p:last-child,.info>p:last-child,.success>p:last-child,.warning>p:last-child{margin-bottom:0}.success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}abbr[title]{cursor:help;border-bottom:1px dotted #777}ul.table-of-contents li{margin:4px 0}.markdown-body table td,.markdown-body table th{word-break:break-all}
-->
线程:
每个Windows进程都有用于进入程序的进入点(entry point)的主线程(Main Thread),例如.Net framework执行程序(控制台、Windows WPF等应用程序)使用Main()方法作为程序的进入点,调用该方法时会自动建立主线程。
线程是Windows进程中的独立执行单元,每个线程都有一个主线程(在执行进入点时建立)并且每个线程还可以以程序方式建立新的线程。
线程的分配与启动需要一定的时间与成本开销,所以这个过程并不是实时的。Task类:
与Thread相比,Task是更抽象的概念,MSDN说明就简单一句:“表示异步操作”,即为能以多线程执行的异步操作,从net framework4.5开始,要建立实现Task后台线程最简单的方式就是使用静态方法Task.Run(),在.Net Framework 4.0可以调用Task.Factory.StartNew方法,可以实现相同的效果
持续工作会告诉Task在完成后继续执行后续的作业,持续工作通常由一个回调方法来实现,它会在任务完成后执行一次。将一个Task加上持续工作有两种方法,
- 第一种是调用Task.ContinueWith方法
- 第二种是.Net Framework4.5新增的Awaiter方法,它非常重要,因为C#5.0的异步功能就是使用这种方式。先看程序代码来说明
Task<int> task=Task.Run(
()=>Enumerable.Range(1,5000000).Count(n=>(n%3)==0);
var awaiter=task.GetAwaiter();
awaiter.OnCompleted(()=>
{
int result=awaiter.GetResult();
Console.WriteLine("整除3的个数有:"+Result);
Console.WriteLine("Task执行中...")
Console.ReadLine();
});
调用Task.GetAwaiter方法会返回一个awaiter(等待者)对象,它会让先前的Task在完成或出错之后执行一个委派,如果先前的Task出现错误,那么当接续工作调用awaited.GetResult()时就会弹出例外。使用GetResult的好处是,当先前的Task出错时,例外可以直接弹出,而不会封装在 aggregateException中。
Task.Delay方法在建立时间延迟之后才会完成的工作,简单地说,它就是Thread.Sleep的异步版本
Parallel类 主要提供并行循环和区域的支持,主要有三个方法For、Foreach、Invoke,主要说一下Invoke方法,Invoke方法会简化启动一组并行操作,它接受一组Action[]数组。
- Async与await关键词 有async修饰词不一定有await运算符,但有await运算符一定有async修饰词,按照微软的建议,开发人员自己编写的异步方法最好也采用“Async”结尾。
- 异步与线程池
当在应用程序中大量使用多线程技术时,首先有一点必须注意。.net framework 会在IIS维护一个线程池,当iis接受到一个请求时,就会从线程池读取一个线程处理的请求,如果使用同步处理程序方式处理此请求,此线程直到程序处理完毕之前,都会一直为自己请求服务,并且此线程无法再为其他请求进行服务,就是所谓的*。
如果线程池够大,就没什么问题,不过线程池的数量是有限的,当有大量突发请求,或可应请求线程都忙于后端高延迟性网络任务时,所有线程池的线程都被*,这种情况称为线程耗尽。发生线程耗尽,IIS会开始将请求排入队列,如果队列已满时,IIS就会拒绝请求,并呈现http503状态,如果异步应用程序正常,但是偶尔会发生http503状态,那么可以开课,事故为县城靠近的情况,可以试着调高队列长度,例如调高至一千。 - 多线程与异步
Task->新线程->读取网络资源
多线程只是换一条线程来代替原本会被锁定的主线程,也就是用线程资源(CPU与内存)换可响应的接口。如果换成异步呢?
异步->线程池->读取网络资源
在线程池中时使用DMA(Direct Memory Access,直接内存访问)模式,直接内存访问是一种不经过CPU而直接进行内存数据读取的机制。CLR提供的异步程序模型就是让开发者充分利用DMA功能来降低CPU压力
所以结论是:
-CPU Bound:适合采用多线程;
-IO Bound:适合采用异步;
下一步是时候看看 .Net Core了。