【亚洲必赢官网】关于异步奉行

理论:

初稿地址: 

(译)关于async与await的FAQ

传送门:异步编制程序系列目录……

        
意况:VS二零一三(固然System.Threading.Tasks在.net四.0就引入,在.net四.5中为其扩张了更丰盛的API及品质进步,其余关键字”async”和”await”是在C#5.0引入的。vs2010打
Visual Studio Async CTP for
VS2010补丁能够引加入关贸总协定组织键字”async”和”await”的支撑,然而得不到.net4.伍新增加API的帮助)

      (CTP:Community Test Preview 社区测试试用版,就是一般的测试版本)

术语:

APM           异步编制程序模型,Asynchronous Programming Model

EAP           基于事件的异步编制程序方式,伊夫nt-based Asynchronous Pattern

TAP           基于职务的异步编制程序情势,Task-based Asynchronous Pattern

         小编不时接到来自开采人士的片段主题素材,这几个主题素材重要汇聚在C#和Visual
Basic中的新重视字”async”和”await”。作者早已将那么些难题分类整理,并借此机会分享给大家。

 

概念概述

  1. 从哪能博取有关”async”和”await”核心的上佳能(CANON)源?

通常,你能在Visual Studio
Async主题中找到大多财富(eg:小说、录像、博客等等)。2011年四月份的MSDN杂志包括了3篇介绍”async”和”await”宗旨的优秀文章。若是您读书,小编推荐你读书顺序依次为:

1) 《通过新的 Visual Studio Async CTP
更轻易地张开异步编制程序》

2) 《通过 Await
暂停和播音》

3) 《了解 Async 和 Await
的成本》

.NET团队博客一样也有”async”和”await”宗旨的理想能源:《Async in .NET四.5:
值得期待》

  1. 为啥需求编写翻译器帮忙大家达成异步编制程序?

亚洲必赢官网,Anders Hejlsberg’s在二零一二微软Build大会上花了贰个钟头来帮大家作证为啥编写翻译器在那边真的可行,录像:《C#和Visual
Basic以往的提升趋势》。简单来说,守旧的异步编制程序模型(APM或EAP)必要您手写多量代码(eg:一连传递委托、回调)来兑现,并且这个代码会招致语句调整流混乱颠倒。通过.NET肆.5提供的新的编制程序模型(TAP),你能够像在写同步代码同样使用正规的依次调节流结合并行任务及”async”和”await”关键字来产生异步编制程序,编译器在后台应用须要的调换以使用回调形式来幸免阻塞线程。

  1. 由此Task.Run() 将同步方法包装成异步职务是还是不是确实有益处?

那取决于你的靶子,你怎么要异步调用方法。倘若你的目的只是想将当前职分切换成另三个线程实施,比如,保险UI线程的响应技巧,那么势必有益。假设您的对象是为了加强可扩展性,那么使用Task.Run()
包装成异步调用将尚未任何实际意义。越多音讯,请看《笔者是否相应领会同步方法对应的异步方法API?》。通过Task.Run()
你能够很轻易的贯彻从UI线程分担职业到另3个做事线程,且可协调后台线程壹旦完毕专业就回去到UI线程。(这里说的可增加性仿佛当扩大cpu时,Task.Run()并不会追加程序的相互效用,因为他只相当于运维了1个线程推行职务,如若使用Parallel.For就持有越来越好的可扩张性。怎样是系统的可扩张性?)

 

“async”关键字

  1. 将尊崇字”async”应用到格局上的功效是怎样?

当你用关键字”async”标志二个主意时,即告诉了编写翻译器两件事:

1)        
你告诉编写翻译器,想在措施内部选用”await”关键字(唯有标记了”async”关键字的主意或lambda表明式技巧利用”await”关键字)。那样做后,编写翻译器会将艺术转化为带有状态机的章程(类似的还有yield的做事原理,请看
《C#稳步基础:古板遍历与迭代器》
),编写翻译后的办法能够在await处挂起并且在await标志的任务到位后异步唤醒。

二)        
你告知编写翻译器,方法的结果或任何大概发生的不胜都将用作重临类型重临。假诺艺术重返Task或Task<TResult>,那象征任何结果值或任何在艺术内部未处理的老大都将积累在回去的Task中。倘使艺术重临void,那意味任何更加会被流传到调用者上下文。

a)         async void函数只幸而UI 伊夫nt回调中使用。

b)         async
void函数中必将在用try-catch捕获全数尤其,不然会很轻松产生程序崩溃。别的索要特别注意lambda表达式,

如:(List<T> 只有 public void ForEach(Action<T> action);
重载)

?

1
Enumerable.Range(0, 3).ToList().ForEach(async (i) => { throw new Exception(); });

那段代码就隐式生成了async void 函数,间接导致了先后的crash。

         可是幸亏,编写翻译器是事先思索生成 async Task
情势的佚名函数的。即如下八个重载,编写翻译器是应用ForEach(Func<T,
Task> action);重载生成async Task 函数。

?

1
2
public void ForEach(Action<T> action);
public void ForEach(Func<T, Task> action);

c)        
注册TaskScheduler.UnobservedTaskException事件,记录Task中未管理卓殊新闻,方便分析及错误定位。

  1. 被”async”关键字标识的不二等秘书籍的调用都会强制调换为异步格局吗?

不会,当您调用二个标记了”async”关键字的法门,它会在此时此刻线程以3头的章程开首运转。所以,若是您有二个1只方法,它回到void并且你做的有所更改只是将其标识的”async”,这一个办法调用照旧是联合具名的。重返值为Task或Task<TResult>也同样。

格局用”async”关键字标识不会影响方法是同步照旧异步运维并做到,而是,它使艺术可被剪切成四个部分,个中部总部分或许异步运营,那样那几个艺术恐怕异步完毕。这几个有些界限就应际而生在措施内部突显采取”await”关键字的职位处。所以,假设在标志了”async”的办法中没有显得应用”await”,那么该措施唯有贰个部分,并且将以联合形式运营并做到。

  1. “async”关键字会导致调用方法被排队到ThreadPool吗?会创设一个新的线程吗?

统统不会,”async”关键字提示编写翻译器在艺术内部恐怕会采用”await”关键字,那样该方法就足以在await处挂起并且在await标志的职务落成后异步唤醒。那也是干什么编写翻译器在编写翻译”async”
标记的不贰秘技时,方法内部从不运用”await”相会世警示的案由(warning CS401四:
由于不等待此调用,因而会在此调用完结前继续施行业前艺术。请思量向此调用的结果运用”await”运算符)。

  1. ”async”关键字能标识任何方法呢?

不能,唯有重临类型为void、Task或Task<TResult>的方法本事用”async”标志。并且,并不是怀有再次来到类型满意上面条件的办法都能用”async”标志。如下,我们分化意采纳”async”标识方法:

一)        
在程序的进口方法(eg:Main()),分化意。当你正在await的任务还未成功,但实践业已回来给艺术的调用者了。Eg:Main(),这将脱离Main(),直接形成退出程序。

2)         在章程包蕴如下特征时,不容许。

l  [MethodImpl(MethodImplOptions.Synchronized)]

为啥那是不允许的,详细请看《What’s New for Parallelism in .NET 4.5
Beta》。此天性将艺术标识为联合类似于选取lock/SyncLock同步基元包裹整个方法体。

l  [SecurityCritical]和[SecuritySafeCritical]   (Critical:关键)

        
编译器在编写翻译一个”async”标记的诀窍,原方法体实际上最终被编写翻译到新生成的MoveNext()方法中,可是其标识的风味还是留存。那意味着天性如[SecurityCritical]不会平常办事。

3)        
在含有ref或out参数的点子中,分化意。调用者期望方法同步调用完成时能保险设置参数值,但是标识为”async”的秘籍可能或不能够担保及时设置参数值直到异步调用落成。

四)        
Lambda被看成表达式树时,不允许。异步lambda表明式不可能被改造为表明式树。

  1. 是或不是有任何约定,这时应该接纳”async”标志方法?

有,基于职分的异步编制程序模型(TAP)是截然专注于咋样贯彻异步方法,那个措施再次回到Task或Task<TResult>。那蕴涵(但不限于)使用”async”和”await”关键字贯彻的法子。想要深切TAP,请看《基于职分的异步编制程序模型》文档。

  1. “async”标识的章程创制的Tasks是不是须求调用”Start()”?

无需,TAP方法再次回到的Tasks是早已正在操作的任务。你不仅没有须要调用”Start()”,而且壹旦你品味也会失败。更加多细节,请看《.NET4.X
并行职务中Task.Start()的FAQ》

  1. “async”标志的艺术创造的Tasks是或不是须求调用”Dispose()”?

无需,一般的话,你无需 Dispose()
任何职分。请看《.NET四.X并行任务Task须求自由吧?》。

  1. “async”是什么关联到近日SynchronizationContext?

对此”async”
标志的方法,借使回去Task或Task<TResult>,则从未主意级的SynchronizationContext交互;对于”async”
标记的办法,假使回到void,则有三个藏匿的SynchronizationContext交互。

当一个”async
void”方法被调用,方法调用的启幕将捕获当前SynchronizationContext(“捕获”在那代表访问它同时将其累积)。假如这里有二个非空的SynchronizationContext,将会影响两件事:(前提:”async
void”)

一)        
在章程调用的启幕将产生调用捕获SynchronizationContext.OperationStarted()方法,并且在造成章程的施行时(无论是同步还是异步)将招致调用捕获SynchronizationContext.OprationCompleted()方法。那给上下文引用计数未变成异步操作提供时机点。借使TAP方法再次来到Task或Task<TResult>,调用者可通过重回的Task做到壹律的追踪。

2)        
要是那个格局是因为未管理的十二分导致方法成功,那么这一个万分将会付出给捕获的SynchronizationContext。这给上下文一个管理错误的时机点。若是TAP方法重临Task或Task<TResult>,调用者可因而重返的Task得到那几个消息。

当调用”async
void”方法时假诺未有SynchronizationContext,未有上下文被捕获,然后也不会调用OperaionStarted/OperationCompleted方法。在这种状态下,若是存在1个未管理过的特别在ThreadPool上传出,那么那会接纳线程池线程暗中认可行为,即导致进度被终止。

 

“await”关键字

  1. “await”关键字做了怎么着

“await”关键字告诉编写翻译器在”async”标志的艺术中插入一个只怕的挂起/唤醒点。

         逻辑上,那象征当您写”await
someObject;”时,编写翻译器将调换代码来检查someObject代表的操作是不是曾经完成。即便已经完毕,则从await标志的唤醒点处继续起初共同推行;倘使未有实现,将为等候的someObject生成一个continue委托,当someObject代表的操作实现的时候调用continue委托。这些continue委托将调控权重新回到到”async”方法对应的await唤醒点处。

重返到await唤醒点处后,不管等待的someObject是还是不是曾经经实现,任何结果都可从Task中领到,或许壹旦someObject操作退步,产生的别的尤其随Task一同回到或回到给SynchronizationContext。

         在代码中,意味着当您写:

         await someObject;

         编写翻译器会转移2个带有 MoveNext 方法的景观机类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
private class FooAsyncStateMachine : IAsyncStateMachine
{
    // Member fields for preserving “locals” and other necessary     state
    int $state;
    TaskAwaiter $awaiter;
    
    public void MoveNext()
    {
        // Jump table to get back to the right statement upon         resumption
        switch (this.$state)
        {
            
        case 2: goto Label2;
            
        }
        
        // Expansion of “await someObject;”
        this.$awaiter = someObject.GetAwaiter();
        if (!this.$awaiter.IsCompleted)
        {
            this.$state = 2;
            this.$awaiter.OnCompleted(MoveNext);
            return;
            Label2:
        }
        this.$awaiter.GetResult();
        
    }
}

在实例 someObject上运用那一个成员来检查该对象是还是不是已到位(通过
IsCompleted),即使未产生,则挂接一个续体(通过
OnCompleted),当所等待实例最后产生时,系统将另行调用 MoveNext
方法,完结后,来自该操作的其他至极将赢得传播或作为结果回到(通过
GetResult),并跳转至上次执行中断的岗位。

  1. 什么是”awaitables”?什么是”awaiters”?

        
固然Task和Task<TResult>是多少个要命广阔的守候类型(“awaitable”),但这并不代表除非那五个的等候类型。

“awaitable”能够是别的项目,它必须公开3个GetAwaiter()
方法并且重返有效的”awaiter”。这么些GetAwaiter()
或然是一个实例方法(eg:Task或Task<TResult>的实例方法),可能大概是3个恢宏方法。

“awaiter”是”awaitable”对象的GetAwaiter()方法再次来到的符合一定的格局的类型。”awaiter”必须兑现System.Runtime.CompilerServices.INotifyCompletion接口(,并可选的兑现System.Runtime.CompilerServices.ICriticalNotifyCompletion接口)。除了提供3个INotifyCompletion接口的OnCompleted方法落成(,可选提供ICriticalNotifyCompletion接口的UnsafeCompleted方法落成),还必须提供三个名称为IsCompleted的Boolean属性以及叁个无参的GetResult()方法。GetResult()再次来到void,假设”awaitable”代表3个void再次回到操作,大概它回到2个TResult,假如”awaitable”代表二个TResult再次来到操作。

两种办法来兑现自定义的”awaitable” 批评,请看《await
anything》。也能针对卓越的气象落成自定义”awaitable”,请看《Advanced
APM Consumption in Async
Methods》和《Awaiting
Socket
Operations》。

  1. 哪些地点不可能选拔”await”?

一)        
在未标志”async”的方法或lambda表明式中,不能运用”await”。”async”关键字告诉编译器其标识的办法内部可以利用”await”。(更详实,请看《Asynchrony
in C# 5 Part Six: Whither
async?》)

二)        
在性能的getter或setter访问器中,不能够动用”await”。属性的意义是高速的归来给调用者,因而不指望利用异步,异步是尤其为潜在的长日子运作的操作。如果你必须在你的质量中央银行使异步,你能够经过兑现异步方法然后在你的习性中调用。

三)        
在lock/SyncLock块中,不能够利用”await”。关于钻探为啥不相同意,以及SemaphoreSlim.WaitAsync(哪三个能用来此景况的守候),请看《What’s
New for Parallelism in .NET 4.5
Beta》【亚洲必赢官网】关于异步奉行。。你仍是能够阅读如下文章,关于什么创设各样自定义异步同步基元:

a)         构建Async同步基元,Part 壹AsyncManualReset伊芙nt

b)         营造Async同步基元,Part 二AsyncAutoReset伊芙nt

c)         创设Async同步基元,Part 3AsyncCountdown伊芙nt

d)         创设Async同步基元,Part 4Async巴里r

e)         创设Async同步基元,Part 5AsyncSemaphore

f)          营造Async同步基元,Part 6AsyncLock

g)         构建Async同步基元,Part 7AsyncReaderWriterLock

四)        
在unsafe区域中,不能够选用”await”。注意,你能在标志”async”的点子内部使用”unsafe”关键字,可是你不能够在unsafe区域中选择”await”。

5)        
在catch块和finally块中,不可能使用”await”。你能在try块中行使”await”,不管它是还是不是有连带的catch块和finally块,不过你不可能在catch块或finally块中接纳”await”。那样做会破坏CL奥迪Q5的十一分管理。

陆)        
LINQ中多数查询语法中,无法利用”await”。”await”大概只用于查询表明式中的第二个集聚表明式的”from”子句或在集中表明式中的”join”子句。

  1. “await task;”和”task.Wait”效果同样啊?

不。

“task.Wait()”是三个同台,大概阻塞的调用。它不会立即回到到Wait()的调用者,直到这些职分进入最后状态,那代表已跻身RanToCompletion,Faulted,或Canceled实现意况。相比较之下,”await
task;”告诉编写翻译器在”async”标志的点子内部插入3个隐蔽的挂起/唤醒点,那样,假设等待的task未有达成,异步方法也会马上回到给调用者,当等待的任务成功时提醒它从隐藏点处继续执行。当”await
task;”会产生比较多应用程序无响应或死锁的情事下使用“task.Wait()”。越来越多消息请看《Await,
and UI, and deadlocks! Oh
my!》。

                  
当你使用”async”和”await”时,还有任何一些隐私缺陷。Eg:

1)        
幸免传递lambda表明式的暧昧缺陷

2)        
确定保证”async”方法毫无被假释

3)        
不要忘记完毕你的职务

4)        
行使”await”依旧恐怕存在死锁?

  1. “task.Result”与”task.GetAwaiter().GetResult()”之间存在功效界别吗?

存在。但可是在职务以非成功景色落成的事态下。假设task是以RanToCompletion状态完结,那么这多少个语句是等价的。可是,若是task是以Faulted或Canceled状态完结,task.Result将盛传二个或多少个十二分封装而成的AggregateException对象;而”task.GetAwaiter().GetResult()”将直接传播非常(即使有四个职责,它只会流传个中二个)。关于为啥会存在这几个差别,请看《.NET四.5中职务的十分管理》。

  1. “await”是什么样关联到日前SynchronizationContext?

那一点壹滴取决于被等候的项目。对于给定的”awaitable”,编译器生成的代码最后会调用”awaiter”的OnCompleted()方法,并且传递将奉行的continue委托。编写翻译器生成的代码对SynchronizationContext一窍不通,仅仅依据当等待的操作实现时调用OnCompleted()方法时所提供的委托。那便是OnCompleted()方法,它担负保险委托在”准确的地点”被调用,”精确的地点”完全由”awaiter”决定。

正值等待的义务(由Task和Task<TResult>的GetAwaiter方法分别再次回到的TaskAwaiter和TaskAwaiter<TResult>类型)的暗许行为是在挂起前抓获当前的SynchronizationContext,然后等待task的达成,假设能捕获到当下的SynchronzationContext,调用continue委托将调整权重临到SynchronizationContext中。所以,比方,借使您在应用程序的UI线程上施行”await
task;”,假如当前SynchronizationContext非空则将调用OnCompleted(),并且在职分落成时,将利用UI的SynchronizationContext传播continue委托重回到UI线程。

当您等待3个任务,假设未有当前SynchronizationContext,那么系统会检查当前的TaskScheduler,假设有,当task完结时将运用TaskScheduler调解continue委托。

一经SynchronizationContext和TaskScheduler都不曾,不能强迫continue委托重返到原先的上下文,也许你选用”await
task.ConfigureAwait(false)替代”await
task;”,然后continue委托不会迫使再次来到到原来上下文并且将允许在系统以为适用的地点持续运营。这一般意味着要么以共同形式运维continue委托,无论等待的task在哪完毕;要么使用ThreadPool中的线程运维continue委托。

  1. 在调整台程序中能使用”await”吗?

理所当然能。但您不能够在Main()方法中使用”await”,因为入口点不可能被标记为”async”。相反,你能在调节台应用程序的别的办法中利用”await”。要是您在Main()中调用那几个措施,你能够同步等待(而不是异步等待)他们的姣好。Eg:

        
你还足以应用自定义的SynchronizationContext或TaskScheduler来实现相似的功效,越多新闻请看:

1)         Await, SynchronizationContext, and Console Apps: Part
1

2)         Await, SynchronizationContext, and Console Apps: Part
2

3)         Await, SynchronizationContext, and Console Apps: Part
3

  1. “await”能和异步编制程序模型形式(APM)或基于事件的异步编制程序方式(EAP)一齐利用呢?

理所当然能,你能够为你的异步操作达成多个自定义的”awaitable”,或许将您现存的异步操作转化为依存的”awaitable”,像task或task<TResult>。示举例下:

1)         Tasks and the APM
Pattern

2)         Tasks and the Event-based Asynchronous
Pattern

3)         Advanced APM Consumption in Async
Methods

4)         Implementing a SynchronizationContext.SendAsync
method

5)         Awaiting Socket
Operations

6)         await
anything

7)         The Nature of
TaskCompletionSource<TResult>

  1. 编写翻译器对async/await生成的代码是还是不是能火速异步施行?

绝大许多动静下,是的。因为大气的浮动代码已经被编写翻译器所优化并且.NET
Framework也为调换代码建构重视关系。要领悟越多音信,包涵运用async/await的最小化费用的最棒实践等。请看

1)        
.NET4.5对TPL的习性升高

2)         二零一一年MVP高峰会议上的“The Zen of
Async”

3)         《了解 Async 和 Await
的成本》

 

一、简介

1、 只要方法是 Task类型的再次回到值,都能够用 await 来等待调用获取重返值。

 

  首先来看看.net的腾飞中的各种阶段的风味:NET 与C#
的每一种版本发布都是有一个“核心”。即:C#一.0托管代码→C#2.0泛型→C#3.0LINQ→C#4.0动态语言→C#4.5异步编程

2、 假诺三个再次来到 Task类型的措施被标志了 async,那么只要方法内部直接return T 那么些 类型的实例即可。

壹块编制程序与异步编制程序

普普通通状态下,大家写的C#代码正是一齐的,运行在同二个线程中,从程序的第3行代码到结尾一句代码顺序实施。而异步编制程序的主旨是使用二十四线程,通过让不相同的线程推行不一的任务,达成不相同代码的互相运维。

 

三、 3个回到 Task类型的法门未有被标识了 async,那么须要艺术内部一贯 Task
实例。

前台线程与后台线程

有关多线程,早在.NET二.0时代,基础类库中就提供了Thread达成。暗中同意景况下,实例化3个Thread创设的是前台线程,只要有前台线程在运维,应用程序的历程就从来处在运维状态,以调控台应用程序为例,在Main方法中实例化3个Thread,这些Main方法就能够等待Thread线程实施落成才脱离。而对于后台线程,应用程序将不考虑其是或不是推行实现,只要应用程序的主线程和前台线程试行完成就足以退出,退出后有着的后台线程将被自动甘休。来看代码应该更明亮一些:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
 
namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("主线程开始");
 
            //实例化Thread,默认创建前台线程
            Thread t1 = new Thread(DoRun1);
            t1.Start();
 
            //可以通过修改Thread的IsBackground,将其变为后台线程
            Thread t2 = new Thread(DoRun2) { IsBackground = true };
            t2.Start();
 
            Console.WriteLine("主线程结束");
        }
 
        static void DoRun1()
        {
            Thread.Sleep(500);
            Console.WriteLine("这是前台线程调用");
        }
 
        static void DoRun2()
        {
            Thread.Sleep(1500);
            Console.WriteLine("这是后台线程调用");
        }
    }
}

运转方面包车型客车代码,能够看出DoRun贰方法的打印消息“那是后台线程调用”将不会被彰显出来,因为应用程序实行完主线程和前台线程后,就活动退出了,全数的后台线程将被活动终止。这里后台线程设置了等候一.五s,借使这一个后台线程比前台线程或主线程提前执行实现,对应的消息“那是后台线程调用”将能够被成功打字与印刷出来。

  上边作者来差不离的介绍一下异步编制程序:异步编制程序,在 .NET Framework 肆.五 和
Windows 运转时行使异步援助。
编写翻译器可举办开采职员曾开始展览的高难度职业,且应用程序保留了贰个像样于联合代码的逻辑结构。
由此,你只需做一小部分职业就足以拿走异步编制程序的有所好处。 

施行(自身足够二个按键):

Task

.NET
肆.0生产了新一代的多线程模型Task。async/await性情是与Task紧凑相关的,所以在摸底async/await前必须充足领悟Task的选拔。这里将以一个简便的德姆o来看一下Task的施用,同时与Thread的创建格局做一下相比较。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Threading;
using System.Threading.Tasks;
 
namespace TestApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("主线程启动");
 
            //.NET 4.5引入了Task.Run静态方法来启动一个线程
            Task.Run(() => { Thread.Sleep(1000); Console.WriteLine("Task1启动"); });
 
            //Task启动的是后台线程,假如要在主线程中等待后台线程执行完毕,可以调用Wait方法
            Task task = Task.Run(() => { Thread.Sleep(500); Console.WriteLine("Task2启动"); });
            task.Wait();
 
            Console.WriteLine("主线程结束");
        }
    }
}
 
Task的使用

先是,必须通晓一点是Task运转的线程是后台线程,不过能够经过在Main方法中调用task.Wait()方法,使应用程序等待task施行完成。Task与Thread的一个主要区分点是:Task底层是使用线程池的,而Thread每一次实例化都会创设1个新的线程。这里能够通过那段代码做二次注解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Threading;
using System.Threading.Tasks;
 
namespace TestApp
{
    class Program
    {
        static void DoRun1()
        {
            Console.WriteLine("Thread Id =" + Thread.CurrentThread.ManagedThreadId);
        }
 
        static void DoRun2()
        {
            Thread.Sleep(50);
            Console.WriteLine("Task调用Thread Id =" + Thread.CurrentThread.ManagedThreadId);
        }
 
        static void Main(string[] args)
        {
            for (int i = 0; i < 50; i++)
            {
                new Thread(DoRun1).Start();
            }
 
            for (int i = 0; i < 50; i++)
            {
                Task.Run(() => { DoRun2(); });
            }
 
            //让应用程序不立即退出
            Console.Read();
        }
    }
}
 
Task底层使用线程池

运作代码,可以观看DoRun一()方法每一回的Thread
Id都以差异的,而DoRun贰()方法的Thread
Id是重新出现的。大家精晓线程的创办和销毁是八个付出相当的大的操作,Task.Run()每一趟实施将不会及时成立2个新线程,而是到CLLacrosse线程池查看是还是不是有空暇的线程,有的话就取二个线程处理那个请求,管理完请求后再把线程放回线程池,那几个线程也不会登时裁撤,而是设置为空闲状态,可供线程池再一次调整,从而收缩费用。

 

亚洲必赢官网 1亚洲必赢官网 2

Task<TResult>

Task<TResult>是Task的泛型版本,那三个里头的最大不一致是Task<TResult>能够有贰个重回值,看一下代码应该一览无余:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Threading;
using System.Threading.Tasks;
 
namespace TestApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("主线程开始");
 
            Task<string> task = Task<string>.Run(() => { Thread.Sleep(1000); return Thread.CurrentThread.ManagedThreadId.ToString(); });
            Console.WriteLine(task.Result);
 
            Console.WriteLine("主线程结束");
        }
    }
}
 
Task<TResult>的使用

Task<TResult>的实例对象有二个Result属性,当在Main方法中调用task.Result的时候,将等待task实践实现并赢得重返值,这里的成效跟调用task.Wait()是平等的,只是多了三个重临值。

  所谓的异步编制程序是选用CPU空闲时间和多核的风味,它所重临的Task或Task<TResult>是对await的2个答应,当职分实践落成后回去三个结实给接收者。这里看到这几个恐怕各位不老子@楚,不妨,上面会有讲授。

private async void button1_Click(object sender, EventArgs e)
        {
            #region 方法一:
            //string i1 = await F1Async();//保证异步任务执行完
            //MessageBox.Show("i1=" + i1);
            //string i2 = await F2Async();
            //MessageBox.Show("i2=" + i2);
            #endregion

            #region 方法二:
            Task<string> task1 = F1Async();
            Task<string> task2 = F2Async();
            string i1 = await task1;//这里保证task1的任务一定执行完,并不是这里才执行异步任务。
            MessageBox.Show("i2=" + i1);
            string i2 = await task2;
            MessageBox.Show("i2=" + i2);
            #endregion
        }
        static Task<string> F1Async()
        {
            MessageBox.Show("F1 Start");
            return Task.Run(() =>
            {
                System.Threading.Thread.Sleep(1000);
                MessageBox.Show("F1 Run");
                return "F1";
            });
        }
        static Task<string> F2Async()
        {
            MessageBox.Show("F2 Start");
            return Task.Run(() =>
            {
                System.Threading.Thread.Sleep(2000);
                MessageBox.Show("F2 Run");
                return "F2";
            });

        }

async/await 特性

经过前边的映衬,终于迎来了那篇小说的台柱async/await,仍然先经过代码来感受一下那八个特性的施用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Threading;
using System.Threading.Tasks;
 
namespace TestApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("-------主线程启动-------");
            Task<int> task = GetLengthAsync();
            Console.WriteLine("Main方法做其他事情");
            Console.WriteLine("Task返回的值" + task.Result);
            Console.WriteLine("-------主线程结束-------");
        }
 
        static async Task<int> GetLengthAsync()
        {
            Console.WriteLine("GetLengthAsync Start"); 
            string str = await GetStringAsync();
            Console.WriteLine("GetLengthAsync End");
            return str.Length;
        }
 
        static Task<string> GetStringAsync()
        {
            return Task<string>.Run(() => { Thread.Sleep(2000); return "finished"; });
        }
    }
}
 
async/await 用法

率先来看一下async关键字。async用来修饰方法,申明这些办法是异步的,表明的艺术的回来类型必须为:void或Task或Task<TResult>。再次来到类型为Task的异步方法中不供给利用return重回值,而回到类型为Task<TResult>的异步方法中务必选用return再次回到2个TResult的值,如上述德姆o中的异步方法重临三个int。

再来看一下await关键字。await必须用来修饰Task或Task<TResult>,而且只可以现身在已经用async关键字修饰的异步方法中。

一般来讲意况下,async/await必须成对出现才有含义,假使一个办法评释为async,但却从未动用await关键字,则那几个艺术在推行的时候就被视作同步方法,那时编译器也会抛出警示提示async修饰的艺术中从未应用await,将被当作壹道方法应用。领悟了重在字async\await的特点后,我们来看一下上述德姆o在支配台会输入什么吗。

亚洲必赢官网 3

输出的结果早就很鲜明地告诉大家任何推行流程了。GetLengthAsync异步方法刚起头是同台实践的,所以”GetLengthAsync
Start”字符串会被打字与印刷出来,直到遭受第三个await关键字,真正的异步任务GetStringAsync开首执行,await也就是起到3个标识/唤醒点的法力,同时将调节权放回给Main方法,”Main方法做其余职业”字符串会被打字与印刷出来。之后由于Main方法要求拜访到task.Result,所以就能够等待异步方法GetLengthAsync的进行,而GetLengthAsync又等待GetStringAsync的施行,壹旦GetStringAsync施行达成,就能够回来await
GetStringAsync那么些点上实践往下进行,这时”GetLengthAsync
End”字符串就能够被打字与印刷出来。

当然,大家也得以运用上面的方法成功地方调控台的出口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Threading;
using System.Threading.Tasks;
 
namespace TestApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("-------主线程启动-------");
            Task<int> task = GetLengthAsync();
            Console.WriteLine("Main方法做其他事情");
            Console.WriteLine("Task返回的值" + task.Result);
            Console.WriteLine("-------主线程结束-------");
        }
 
        static Task<int> GetLengthAsync()
        {
            Console.WriteLine("GetLengthAsync Start");
            Task<int> task = Task<int>.Run(() => { string str = GetStringAsync().Result;
                Console.WriteLine("GetLengthAsync End");
                return str.Length; });          
            return task;
        }
 
        static Task<string> GetStringAsync()
        {
            return Task<string>.Run(() => { Thread.Sleep(2000); return "finished"; });
        }
    }
}
 
不使用async\await

对照两种方法,是或不是async\await关键字的原理其实正是由此采纳二个线程达成异步调用吗?答案是不是认的。async关键字标明能够在点子内部接纳await关键字,方法在推行到await前都以联合试行的,运维到await处就能够挂起,并赶回到Main方法中,直到await标志的Task奉行完结,才提示回到await点上,继续向下实行。更深入点的牵线能够查阅作品最终的参考文献。

 

View Code

async/await 实际应用

微软曾经对有些基础类库的法子提供了异步落成,接下去将贯彻1个事例来介绍一下async/await的其实使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Threading;
using System.Threading.Tasks;
using System.Net;
 
namespace TestApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("开始获取博客园首页字符数量");
            Task<int> task1 = CountCharsAsync("http://www.cnblogs.com");
            Console.WriteLine("开始获取百度首页字符数量");
            Task<int> task2 = CountCharsAsync("http://www.baidu.com");
 
            Console.WriteLine("Main方法中做其他事情");
 
            Console.WriteLine("博客园:" + task1.Result);
            Console.WriteLine("百度:" + task2.Result);
        }
 
        static async Task<int> CountCharsAsync(string url)
        {
            WebClient wc = new WebClient();
            string result = await wc.DownloadStringTaskAsync(new Uri(url));
            return result.Length;
        }
    }
}

2、使用表明

 

艺术签字包涵3个 Async 或 async 修饰符。

 

依照预订,异步方法的名号以“Async”后缀结尾。

 

回去类型为下列项目之一:

 

只要您的秘技有操作数为 TResult 类型的回来语句,则为
Task<TResult>。

 

假设您的不二秘诀未有回到语句或有所未有操作数的归来语句,则为 Task。

 

假定您编写的是异步事件管理程序,则为 Void(Visual Basic 中为 Sub)。

 

关于详细新闻,请参见本主旨前边的“再次回到类型和参数”。

 

方法一般包括至少3个 await
表明式,该表明式标志三个点,在该点上,直到等待的异步操作落成章程技术继续。
同时,将艺术挂起,并且控件重临到方法的调用方。(这里所谓的挂起便是上文所涉嫌的许诺,异步方法承诺会给调用方贰个结果)

 

三、示例

  实施才是查看真理的极品路径。

 

 

using System;

using System.Diagnostics;

using System.Net.Http;

using System.Threading.Tasks;

 

namespace 异步递归

{

    class Program

    {

        static void Main(string[] args)

        {

            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();

            ConsoleAsync1();

            stopwatch.Stop();

            Console.WriteLine(“同步方法用时:” +
stopwatch.Elapsed米尔iseconds);

            stopwatch.Reset();

            stopwatch.Start();

            ConsoleAsync();

            stopwatch.Stop();

            Console.WriteLine(“异步方法用时:”+
stopwatch.ElapsedMilliseconds);

 

            Console.Read();

        }

 

        private static async void ConsoleAsync()

        {

            Console.WriteLine(“异步方法伊始”);

            Console.WriteLine(“Result:” + await SumAsync(10));

            Console.WriteLine(“异步方法截至”);

        }

        private static async Task<int> SumAsync(int part)

        {

            if ((part += 10) >= 100)

            {

                return 100;

            }

            HttpClient client = new HttpClient();

            Task<string> getStringTask =
client.GetStringAsync(“”);

            Console.WriteLine(DateTime.Now.Millisecond + ” 异步 ” +
(await getStringTask).Length);

            return await SumAsync(part);

        }

 

        private static void ConsoleAsync1()

        {

            Console.WriteLine(“同步方法开头”);

            Console.WriteLine(“Result:” + SumAsync1(10));

            Console.WriteLine(“同步方法甘休”);

        }

 

        private static int SumAsync1(int part)

        {

            if ((part += 10) >= 100)

            {

                return 100;

            }

            HttpClient client = new HttpClient();

            Task<string> getStringTask =
client.GetStringAsync(“”);

            Console.WriteLine(DateTime.Now.Millisecond + ” 同步 ” +
getStringTask.Result.Length);

            return SumAsync1(part);

        }

    }

}

 

  示例介绍:

 

    壹、那几个事例中有二种完结情势:(壹)利用异步编制程序的法子达成(贰)利用常见同步格局落成

 

    二、同时这么些事例中贯彻了递归,那个能够不要思念,博主只是想说圣元(Synutra)(Karicare)下在异步的境况下,递归是或不是可行而已,实验结果为有效。

 

    三、那段代码中的GetStringAsync()方法是收获远程分界面内容用的,首要目标是延长响应时间。

 

  在选取八线程编写端口扫描程序时,作者要好认为到同步和规定全数线程都试行完的时日是二个相比麻烦的标题。有园友讨论说未来曾经不手动创制thread对象了,而是向来动用Task异步情势,笔者的网络编制程序老师也讲到了异步编制程序的优越性。在学习了课本上的学问后,进行了三个总计分享给大家。从.NET4.五方始,用async和await关键字再拉长Task.Run是3个不胜科学的异步编制程序模型。

1.await和async

  异步情势从工夫上看正是行使委托来兑现的,它的第贰利润是在异步实施的经过中,用户仍可以够操控UI分界面。使用Task类和使用Thread类有不少相似的地点,Task类也是经过调用方法去落到实处二个职分的实现,方法但是是命名格局或佚名格局,在实施进度中可利用async和await来落到实处异步施行。async是一个修饰符,它不得不用在格局依然事件管理程序的签订契约中。对于措施可分为有再次来到值和无再次来到值二种情况,事件则唯有1种,如上边三条语句所示:

    private async Task<int> MethodAsync();//有重返值的异步方法

    private async Task MethodAsync();//无再次回到值的异步方法

    private async void btnOk_Click();//异步事件管理程序

  await是叁个运算符,它表示等待异步奉行的结果。也足以精通为await运算符实际上是对章程的重临值进行操作,相当于对Task<Result>进行操作,而不是对艺术本身举行操作。还有有个别要小心,await是必然要放在异步方法的中间,假使未有放在中间的话,VS会自行报错。以下是async和await使用的例证: 

    private async void button5_Click(object sender, EventArgs e)
    {
      Task a = Method1Async();
      //此处可继续施行别的代码
      await a;//等待任务a落成
      Task<int> b = Method2Async();
      //此处可继续施行别的代码
      int c = await b;//等待职分b达成,且能够得到义务b的重回值
    }

    Task Method1Async();
    async Task<int> Method2Async()
    {
      await Task.Delay(100);
      return 1;
    }

  await和一齐编制程序最大的分裂之处是:异步等待职责到位的时候,在不会继续施行后边的代码时,也不会潜移默化分界面的操作。在.NET提供的类中,异步方法都以预约用Async作为后缀,这样能够很明亮的知晓那一个方法是异步方法或许1道方法。

二. 成立职务

  成立任务也便是将职分与要实践的无与伦比联系起来,编写职务推行的形式时,那一个办法既能够是同台方法也足以是异步方法,仍是可以是无名氏情势。实践异步方法时,必须用async和Task共同表示尚无重回值的天职,用async和Task<TResult>共同表示再次回到值为TResult的职责。以下是概念试行职责的主意。

    private async void button5_Click(object sender, EventArgs e)
    {

      //Task.Run方法表示使用默许的职分调治程序在线程池中通过后台实践钦点的职务

      //如若不需求本身去调整措施,使用那几个方法最方便
      await Task.Run(()=>Method1Async());//实施一同方法
      int c = await
Task.Run(()=>Method二Async());//实施异步方法
      await Task.Run(async () => { c = 二;
});//试行异步佚名格局
    }
    void Method1Async();
    async Task<int> Method2Async(){…}

  Task.Run方法常用的重载格局有以下四种,其它它也是能够用new关键字显得创制职务,不过那种办法用的不多。

    Task Run(Func<Task> function);//实行不带再次来到值的义务

    Task<TResult>
Run<TResult>(Func<Task<TResult>>
function);//实践带重回值的职分

    Task<TResult> Run<TResult>(Func<Task<TResult>>
function, CancellationToken
cancellationToken);//施行进程中能够监听撤消通告

    Task Run(Func<Task> function, CancellationToken
cancellationToken);//实践进度中能够监听撤销文告

叁. 悬停职分

  在实践职分时一定会出现需求截止职务的境况,这里的停歇告诉职分你要赶早停下来不再试行了,而不是直接销毁职务实例。这里能够打个比如,学生一同出去吃饭了,学生与教师都在班群里面,突然班群里老师说要让同学们集聚,假设具备同学都看到这些消息,然后学生们起头启程,那样就可以正确的联谊。上边的例子有贰个很主要的前提,那正是颇具同学都要见到那一个消息,相当于学员是时刻监听音信的。CancellationTokenSource类和CancellationToken结构用于得以落成十二线程、线程池和Task职务的吊销操作,管理情势与地点的事例相似。创制的班群正是CancellationTokenSource对象,收到的料理便是CancellationToken对象。CancellationTokenSource用于创设撤除文告,CancellationToken则用于传播应注销操作的布告,当调用职责前,能够先创立打消源对象CancellationTokenSource
cts=new CancellationTokenSource();,假若愿目的在于30秒后自行发出打消毁文件告,能够流传参数CancellationTokenSource(TimeSpan.FromSeconds(30));CancellationToken
ct=cts.Token;,后一句代码是得到撤销的布告。CancellationTokenSource还有三个Cancel方法,将那一个性情设为true时,该方法会将具有增加了吊销标记的CancellationToken对象的IsCancellationRequested属性都安装为true,那样打消布告就传递到了正在推行的职分。

  任务收到撤消通告后,能够选用三种方法来终止操作。第一种办法是回顾的从委托重临。那种达成格局接近于在调用职责的代码中3个bool值来代表撤废布告,任务收到后就直接重临了。当使用那种办法时义务状态的再次回到值为TaskStatus.RanToCompletion枚举值,它代表符合规律落成,而不是TaskStatus.Canceled枚举值。第二种方式是在代码里抓住OperationCanceledException极度,并将其传递到在其上呼吁了收回的暗号,接纳那种方法收回的任务会转变为用Canceled枚举值表示的场所。落成引发那些的首选办法是调用ct.ThrowIfCancellationRequestes();。以下是代码示例,写了3个winform程序,利用进度条来撤废任务。第三个图是不曾抓住这几个时,程序退出for循环,施行后边的代码后回到了,第三张图是第1种方法,引发了丰富后直接跳转到catch语句块了。

亚洲必赢官网 4

亚洲必赢官网 5

亚洲必赢官网 6

     CancellationTokenSource cts;
        private async void button3_Click(object sender, EventArgs e)
        {
            progressBar1.Maximum = 100;
            progressBar1.Value = 0;
            cts = new CancellationTokenSource();
            var aa = MYThreadAsync("a", cts.Token);
            try
            {
                await aa;
                listBox1.Items.Add("await后面");
            }
            catch
            {
                if (aa.IsCanceled)
                    listBox1.Items.Add("a取消");
            }
        }

        private void button4_Click(object sender, EventArgs e)
        {
            cts.Cancel();
        }

        public async Task MYThreadAsync(string s, CancellationToken ct)
        {
            for (int i = 0; i < 50; i++)
            {
                if (ct.IsCancellationRequested)
                    break;          //点击关闭按钮,IsCancellationRequested就为true,就会退出for循环,这是第一种方式
                progressBar1.Value += 2;
                await Task.Delay(100);
                ct.ThrowIfCancellationRequested();//这是第二种方式,它会终止任务并且返回catch语句块里面
            }
            listBox1.Items.Add("任务" + s + "完成了");
        }

亚洲必赢官网 7

四. 得到任务执行的状态

  在异步编制程序中,很分明职务奉行的景观是1个丰硕重要的参数。在职责的生命周期里,能够经过Status属性来收获职分实施的情状,当任务到位后还足以由此职责属性知道义务完毕的情状。可选择任务实例的Status属性获取任务推行的情事,义务推行的情事用TaskStatus枚举表示,以下是TaskStatus的枚举值:

Created:职务现已初阶化,但没有进入调节布署

WaitingForActivation:该职责已跻身调解安顿,正在守候被调整程序激活

WaitingToRun:该职务已被调治程序激活,但尚无开首要推荐行

Running:该义务正在运营,但绝非完结

RanToCompletion:该职务已经成功做到

Canceled:该职责由于被撤消而成就,引发那些或调用方已向该职分的CancellationToken发出非数字信号

Faulted:该职务因为现身未经处理的10分而实现

WaitingForChildrenToComplete:该职责自己已到位,正等待附加的子职务落成

  职务成功景况有关的天性有IsCompleted、IsCanceled和IsFaulted等质量,从单词意思上看简单明白它们的意趣,在那之中要留心IsCompleted属性表示职务是还是不是做到,无论是平常甘休照旧因为撤消或尤其而做到都为变成。

五. 职分实行的速度

  有时候我们盼望让某个异步操作提供进程通报,以便在分界面中显示异步操作实行的速度,可以用Progress<T>类来得到任务施行的快慢。以下是应用格局里的Report方法将艺术内变量的值传回成立职分的事件代码里,从而立异进程条的值。

亚洲必赢官网 8

     CancellationTokenSource cts;
        private async void button3_Click(object sender, EventArgs e)
        {
            progressBar1.Maximum = 100;
            progressBar1.Value = 0;
            cts = new CancellationTokenSource();
            CancellationToken ct = cts.Token;
            var pp = new Progress<int>();
            pp.ProgressChanged += (s, n) => {
                progressBar1.Value = n;
            };
            var tt = Task.Run(()=>MYThreadAsync(pp,cts.Token,500),cts.Token);
            try
            {
                await tt;
                if (tt.Exception == null)
                    listBox1.Items.Add("任务完成");
            }
            catch (Exception ex)
            {
                listBox1.Items.Add("异常" + ex.Message);
            }
        }         
        private void button4_Click(object sender, EventArgs e)
        {
            cts.Cancel();
        }
        public  void MYThreadAsync(IProgress<int> progress, CancellationToken ct, int delay)
        {
            int p = 0;//进度
            while (p < 100 && ct.IsCancellationRequested == false)
            {
                p += 1;
                Thread.Sleep(delay);
                progress.Report(p);//这个方法将会触发ProgressChanged事件更新进度条
            }
        }

亚洲必赢官网 9

陆. 按期达成职分

  无论是服务器依然客户端,都以有定期落成有个别职分的内需的。System.Timers.Timer类是叁个正确的定期设置类,那一个类能够吸引事件,但它暗中同意是在线程池中引发风云,而不是在脚下线程中吸引轩然大波。Timer类的常用属性有AutoReset和Interval属性,AutoReset是赢得或设置叁个bool值,该值为true表示每一遍间隔结束时都引发一回Elapsed轩然大波,false表示仅在第叁回间隔停止时引发一遍该事件。Interval属性是获得或设置三次Elapsed事件的间隔时间,该值必须大于零并小于Int.马克斯Value,默许值为100纳秒。Timer类还有五个常用艺术那正是Start和Stop方法。

  还有1个System.Threading.Timer类,它也是在线程池中定期施行职责,它与前3个Timer类的界别是此类不行使事件模型,而是径直通过TimerCallback类型的嘱托来落实的。该类的构造函数为:Timer(TimerCallback
callback,Object state,提姆eSpan dou提姆e,TimeSpan
period)。callback代表要实行的主意,state代表一个带有回调方法要选取的新闻的靶子,dueTime是第壹遍调用回调方法在此以前延迟的年华,period表示每一次调用回调方法的小运距离,-一代表终止。那样创立对象后,第一回达到dueTime延时时间会自动调用一回callback委托,今后每隔period时间间隔调用三回。以下是那二种艺术的运作效果和源代码。亚洲必赢官网 10

 

亚洲必赢官网 11

     System.Timers.Timer timer;
        System.Threading.Timer threadtimer;
        private void button2_Click(object sender, EventArgs e)//Timers.Timer
        {
            progressBar1.Maximum = 100;
            progressBar1.Value = 0;
            int pro=0;
            timer = new System.Timers.Timer(500);
            timer.AutoReset = true;
            timer.Elapsed+= (obj, args) =>
            { 
                pro+=5;
                progressBar1.Value = pro;
            };
            timer.Start();
        }

       private void button5_Click(object sender, EventArgs e)
       {
           timer.Stop();
           listBox1.Items.Add("第一个已经停止");
       }
    //Threading.Timer类
       private void button1_Click(object sender, EventArgs e)
       {
           progressBar2.Maximum = 100;
           progressBar2.Value = 0;
           TimeSpan dueTime = new TimeSpan(0, 0, 0, 1);
           TimeSpan period = new TimeSpan(0, 0, 0, 0, 200);
           System.Threading.TimerCallback timecall = new TimerCallback((obj) => progressBar2.Value += 5);
           threadtimer = new System.Threading.Timer(timecall, null, dueTime, period);
       }

       private void button6_Click(object sender, EventArgs e)
       {
           threadtimer.Dispose();
           listBox1.Items.Add("第二个已经停止");
       }

亚洲必赢官网 12

  这篇文章只总括了单个任务的异步试行的基本功,还得继续攻读多职责并行推行。若是有更加好的本事依然与商铺采纳有关的异步才能,希望园友能够建议本身继续学习。

网站地图xml地图