c# 基于任务的异步编程模式(TAP)

异步编程是C#5.0的一个重要改进,提供两个关键字:async和await。使用异步编程,方法的调用是在后台运行(通常在线程或任务的帮助下),但不会阻塞调用线程。异步模式分为3种:异步模式、基于事件的异步模式和基于任务的异步模式(TAP)。TAP是利用关键字async和await实现的,本文将讲解TAP模式。async和await关键字只是编译器的功能。编译器最终会用Task类创建代码。

1、创建任务

建立一个同步方法Greeting,该方法在等待一段时间后,返回一个字符串。

 private string Greeting(int delay, string name)
 {
   System.Threading.Thread.Sleep(delay);
   return string.Format("Hello, {0}.", name);
 }

定义一个方法GreetingAsync,可以使方法异步化,其传入的参数不做强制要求。基于任务的异步模式指定,并返回一个任务。注意,该方法返回的是Task<string>,定义了一个返回字符串的任务,与同步方法返回值一致。

private Task<string> GreetingAsync(string name, int delay = 3000)
{
  return Task.Run<string>(() =>
  {
    return Greeting(delay, name);
  });
}

2、调用异步方法

可以使用await关键字调用返回任务的异步方法GreetingAsync。但是,使用await关键字的方法必须要用async关键字修饰符声明。在GreetingAsync方法完成前,被async关键字修饰的方法内await关键字后面的代码不会继续执行。但是,启动被async关键字修饰的方法的线程可以被重用,而没有被阻塞。

public async void CallerWithAsync()
{
  string result = await GreetingAsync("Nigel", 2000);
  Console.WriteLine(result);
}

注意:async修饰符修饰只能用于返回Task或void的方法。不能作为程序的入口点,即Main方法不能使用async修饰符。await修饰符只能用于返回Task的方法。

3、延续任务

GreetingAsync方法返回一个Task<string>对象。该对象包含任务创建的信息,并保存到任务完成。Task类的ContinueWith方法可在任务完成后继续调用的代码。

public void CallsWithContinuationTask()
 {
   Task<string> task = GreetingAsync("Stephanie", 1000);
   task.ContinueWith(t =>
   {
     Console.WriteLine(t.Result);
   });
 }

实际上,编译器会把await关键字后的所有代码放进ContinueWith方法内。不论是await关键字的方法还是任务的ContinueWith方法,在方法的不同生命阶段使用了不同的线程。都是当await关键字的方法或任务执行完毕后,再由另一个线程去执行await关键字后面的代码,或给当前线程添加新的任务去执行相关代码。

在具有UI的应用程序中,应用程序的窗体的控件不允许跨线程访问,需要使用控件的InvokeRequired属性和Invoke方法,将访问UI的方法代码块以委托的形式传递给控件的Invoke,但是在执行前需要判断控件的InvokeRequired。在使用async和await关键字,当await完成后,不需要做任何处理,就可以放访问UI线程(实际上是将控制权又交给了UI线程)。

4、使用多个异步方法

4.1、按顺序调用多个异步方法

使用await关键字可以调用每个异步方法。如果一个异步方法依赖于另一个异步方法,将会起到很大作用。但当异步方法之间没有相互依赖的时候,不使用await关键字将更快返回结果。

public async void MultipleAsyncMethods()
 {
   DateTime start = DateTime.Now;
   string result1 = await GreetingAsync("Jack",2500);//先执行完它
   string result2 = await GreetingAsync("Tim",1500);//再执行它
   //输出结果
   Console.WriteLine("Finished both methods: MultipleAsyncMethods.\nResult 1: {0}, Result 2: {1}", result1, result2);
   Console.WriteLine("Use time: {0}", (DateTime.Now - start).TotalMilliseconds);
 }

4.2、使用组合器

如果任务之间并不依赖于另一个任务,每个异步方法都不需要使用await,而是把每个异步方法的返回结果赋值给Task变量,使用组合器让这些任务并行运行。当组合器内的所有任务都完成后,才会执行后面的代码。

public async void MultipleAsyncMethodsWithCombinators1()
{
  DateTime start = DateTime.Now;
  Task<string> t1= GreetingAsync("Jack", 2500);
  Task<string> t2= GreetingAsync("Tim", 1500);
  await Task.WhenAll(t1, t2);
  //输出结果
  Console.WriteLine("Finished both methods: MultipleAsyncMethodsWithCombinators1.\nResult 1: {0}, Result 2: {1}", t1.Result, t2.Result);
  Console.WriteLine("Use time: {0}", (DateTime.Now - start).TotalMilliseconds);
}

如果所有任务类型都返回相同的类型,则可用该类型的数组作为await返回的结果

public async void MultipleAsyncMethodsWithCombinators2()
{
  DateTime start = DateTime.Now;
  Task<string> t1 = GreetingAsync("Jack", 2500);
  Task<string> t2 = GreetingAsync("Tim", 1500);
  string[] results= await Task.WhenAll(t1, t2);
  //输出结果
  Console.WriteLine("Finished both methods: MultipleAsyncMethodsWithCombinators2.\nResult 1: {0}, Result 2: {1}", results[0], results[1]);
  Console.WriteLine("Use time: {0}", (DateTime.Now - start).TotalMilliseconds);
}

5、异步方法的异常处理

如果调用异步方法,但是没有等待,那么调用异步方法的线程中使用传统的try/catch块是不能捕获到异步方法中的异常。因为在异步方法执行出现异常之前,已经执行完毕。

如何捕获异常见《基于任务的异步编程模式(TAP)的错误处理》。

以上就是c# 基于任务的异步编程模式(TAP)的详细内容,更多关于c# 异步编程的资料请关注我们其它相关文章!

(0)

相关推荐

  • 深入分析C#异步编程详解

    同步方法和异步方法的区别同步方法调用在程序继续执行之前需要等待同步方法执行完毕返回结果异步方法则在被调用之后立即返回以便程序在被调用方法完成其任务的同时执行其它操作异步编程概览.NET Framework 允许您异步调用任何方法.定义与您需要调用的方法具有相同签名的委托:公共语言运行库将自动为该委托定义具有适当签名的 BeginInvoke 和 EndInvoke 方法.BeginInvoke 方法用于启动异步调用.它与您需要异步执行的方法具有相同的参数,只不过还有两个额外的参数(将在稍后描述)

  • C#异步编程详解

    前言 本节主要介绍异步编程中Task.Async和Await的基础知识. 什么是异步? 异步处理不用阻塞当前线程来等待处理完成,而是允许后续操作,直至其它线程将处理完成,并回调通知此线程. 异步和多线程 相同点:避免调用线程阻塞,从而提高软件的可响应性. 不同点: 异步操作无须额外的线程负担,并且使用回调的方式进行处理,在设计良好的情况下,处理函数可以不必使用共享变量(即使无法完全不用,最起码可以减少 共享变量的数量),减少了死锁的可能.C#5.0 .NET4.5 以后关键字Async和Awai

  • C#实现异步编程的方法

    最近在我参与的几个.Net项目中都有用到异步编程,作为一名.Net小白,很有必要好好地学习一下C#异步编程. 什么是异步 异步指的就是不用阻塞当前线程来等待任务的完成,而是将任务扔到线程池中去执行,当前线程可以继续向下执行,直至其它线程将任务完成,并回调通知当前线程.整个任务从开始到结束都是异步完成的,不会阻塞当前线程.因此,异步很重要的一点就是,不会阻塞当前线程. 实现异步编程 在C#语言中,主要是通过委托来实现异步编程的,在委托类型中定义了两个方法BeginInvoke()和EndInvok

  • C#异步编程几点需要注意的地方

    尽量不要编写返回值类型为void的异步方法 在通常情况下,建议大家不要编写那种返回值类型为void的异步方法,因为这样做会破坏该方法的启动者与方法本身之间的约定,这套约定本来可以确保主调方能够捕获到异步方法所发生的异常. 正常的异步方法是通过它返回的Task对象来汇报异常的.如果执行过程中发生了异常,那么Task对象就进入了faulted(故障)状态.主调方在对异步方法所返回的Task对象做await操作时,该对象若已处在faulted状态,系统则会将执行异步方法的过程中所发生的异常抛出,反之,

  • C#编程总结(六)详解异步编程

    1.什么是异步? 异步操作通常用于执行完成时间可能较长的任务,如打开大文件.连接远程计算机或查询数据库.异步操作在主应用程序线程以外的线程中执行.应用程序调用方法异步执行某个操作时,应用程序可在异步方法执行其任务时继续执行. 2.同步与异步的区别 同步(Synchronous):在执行某个操作时,应用程序必须等待该操作执行完成后才能继续执行. 异步(Asynchronous):在执行某个操作时,应用程序可在异步操作执行时继续执行.实质:异步操作,启动了新的线程,主线程与方法线程并行执行. 3.异

  • c# 使用异步编程的方法

    怎么使用异步,就是用委托进行处理,如果委托对象在调用列表中只有一个方法,它就可以异步执行这个方法.委托类有两个方法,叫做BeginInvoke和EndInvoke,它们是用来异步执行使用. 异步有三种模式 等待模式,在发起了异步方法以及做了一些其它处理之后,原始线程就中断,并且等待异步方法完成之后再继续. 轮询模式,原始线程定期检查发起的线程是否完成,如果没有则可以继续做一些其它的事情. 回调模式,原始线程一直在执行,无需等待或检查发起的线程是否完成.在发起的线程中的引用方法完成之后,发起的线程

  • c# 基于任务的异步编程模式(TAP)的异常处理

    在前面讲到了<基于任务的异步编程模式(TAP)>,但是如果调用异步方法,没有等待,那么调用异步方法的线程中使用传统的try/catch块是不能捕获到异步方法中的异常.因为在异步方法执行出现异常之前,已经执行完毕. 1.没有等待的调用异步方法 ThrowAfter方法是在一定延迟后抛出一个异常: private async Task ThrowAfter(int ms,string message) { await Task.Delay(ms); Console.WriteLine("

  • c# 基于任务的异步编程模式(TAP)

    异步编程是C#5.0的一个重要改进,提供两个关键字:async和await.使用异步编程,方法的调用是在后台运行(通常在线程或任务的帮助下),但不会阻塞调用线程.异步模式分为3种:异步模式.基于事件的异步模式和基于任务的异步模式(TAP).TAP是利用关键字async和await实现的,本文将讲解TAP模式.async和await关键字只是编译器的功能.编译器最终会用Task类创建代码. 1.创建任务 建立一个同步方法Greeting,该方法在等待一段时间后,返回一个字符串. private s

  • .NET2.0版本中基于事件的异步编程模式(EAP)

    一.引言 APM为我们实现异步编程提供了一定的支持,同时它也存在着一些明显的问题——不支持对异步操作的取消和没有提供对进度报告的功能,对于有界面的应用程序来说,进度报告和取消操作的支持也是必不可少的. 微软在.NET 2.0的时候就为我们提供了一个新的异步编程模型,也就是基于事件的异步编程模型——EAP(Event-based Asynchronous Pattern ). 二.介绍 实现了基于事件的异步模式的类将具有一个或者多个以Async为后缀的方法和对应的Completed事件,并且这些类

  • C#实现基于任务的异步编程模式

    目录 一.延续任务 二.同步上下文 三.使用多个异步方法 1.按顺序调用异步方法 2.使用组合器 四.转换异步模式 五.错误处理 1.异步方法的异常处理 2.多个异步方法的异常处理 3.使用AggregateException信息返回显示异常 六.取消异步方法 一.延续任务 private async static void CallerWithAsync() { string result = await GreetingAsync("Stephanie"); Console.Wri

  • 基于javascript的异步编程实例详解

    本文实例讲述了基于javascript的异步编程.分享给大家供大家参考,具体如下: 异步函数这个术语有点名不副实,调用一个函数后,程序只在该函数返回后才能继续.JavaScript程序员如果称一个函数为异步的,其意思就是这个函数会导致将来再运行另一个函数,后者取自于事件队列.如果后面这个函数是作为参数传递给前者的,则称其为回调函数. callback 回调函数是异步编程最基本的方式. 采用这种方式,我们把同步操作变成了异步操作,主函数不会堵塞程序运行,相当于先执行程序的主要逻辑,将耗时的操作推迟

  • JavaScript中实现异步编程模式的4种方法

    你可能知道,Javascript语言的执行环境是"单线程"(single thread). 所谓"单线程",就是指一次只能完成一件任务.如果有多个任务,就必须排队,前面一个任务完成,再执行后面一个任务,以此类推. 这种模式的好处是实现起来比较简单,执行环境相对单纯:坏处是只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行.常见的浏览器无响应(假死),往往就是因为某一段Javascript代码长时间运行(比如死循环),导致整个页面卡在这个地方,其他

  • .NET异步编程模式的三种类型介绍

    一.引言 .NET中很多的类.接口在设计的时候都考虑了多线程问题,简化了多线程程序的开发,不用自己去写WaitHandler等这些底层的代码,由于历史的发展,这些类的接口设计有着三种不同的风格:EAP.APM和TPL.目前重点用TPL. 二.EAP EAP是Event-based Asynchronous Pattem(基于事件的异步模型)的简写,类似于Ajax中的XmlHttpRequest,send之后并不是处理完成了,而是在onreadystatechange事件中再通知处理完成.看下面的

  • 浅谈Async和Await如何简化异步编程(几个实例让你彻底明白)

    引言 C#5.0中async和await两个关键字,这两个关键字简化了异步编程,之所以简化了,还是因为编译器给我们做了更多的工作,下面就具体看看编译器到底在背后帮我们做了哪些复杂的工作的. 同步代码存在的问题 对于同步的代码,大家肯定都不陌生,因为我们平常写的代码大部分都是同步的,然而同步代码却存在一个很严重的问题,例如我们向一个Web服务器发出一个请求时,如果我们发出请求的代码是同步实现的话,这时候我们的应用程序就会处于等待状态,直到收回一个响应信息为止,然而在这个等待的状态,对于用户不能操作

  • .NET中基于事件的异步模式-EAP

    前言 在C# 5.0中,新增了async await 2个关键字支持异步编程的操作.在讲述这两个关键字之前,我先总结一下.NET中的常见的异步编程模型. 异步编程一直是比较复杂的问题,其中要处理多线程之间的数据同步.获取进度.可取消.获取结果.不影响主线程操作.多个任务之间互相不影响等,因此需要设计编程模型去处理此类问题. 从.NET 4.5开始,支持的三种异步编程模式: 基于事件的异步编程设计模式 (EAP,Event-based Asynchronous Pattern) 异步编程模型(AP

  • .NET中的异步编程-EAP/APM使用方法及案例介绍

    从.NET 4.5开始,支持的三种异步编程模式: •基于事件的异步编程设计模式 (EAP,Event-based Asynchronous Pattern) •异步编程模型(APM,Asynchronous Programming Model) •基于任务的编程模型(TAP,Task-based Asynchronous Pattern) 基于任务的异步模式 (TAP) 是基于 System.Threading.Tasks 命名空间的 Task 和 Task<TResult>,用于表示任意异步

随机推荐