服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - c# 基于任务的异步编程模式(TAP)

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

2022-10-13 13:28一只独行的猿 C#

这篇文章主要介绍了c# 基于任务的异步编程模式(TAP)的相关资料,帮助大家更好的理解和学习c# 异步编程的相关知识,感兴趣的朋友可以了解下

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

1、创建任务

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

?
1
2
3
4
5
private string Greeting(int delay, string name)
{
 System.Threading.Thread.Sleep(delay);
 return string.Format("Hello, {0}.", name);
}

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

?
1
2
3
4
5
6
7
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关键字修饰的方法的线程可以被重用,而没有被阻塞。

?
1
2
3
4
5
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方法可在任务完成后继续调用的代码。

?
1
2
3
4
5
6
7
8
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关键字将更快返回结果。

?
1
2
3
4
5
6
7
8
9
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变量,使用组合器让这些任务并行运行。当组合器内的所有任务都完成后,才会执行后面的代码。

?
1
2
3
4
5
6
7
8
9
10
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返回的结果

?
1
2
3
4
5
6
7
8
9
10
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# 异步编程的资料请关注服务器之家其它相关文章!

原文链接:https://www.cnblogs.com/pilgrim/p/9147313.html

延伸 · 阅读

精彩推荐
  • C#C# 如何规范的写 DEBUG 输出

    C# 如何规范的写 DEBUG 输出

    本文来告诉大家一个规范,如何去写 DEBUG 的输出。本文给大家介绍的非常详细,需要的朋友参考下吧...

    lindexi11542022-02-17
  • C#C#实现导出List数据到xml文件的方法【附demo源码下载】

    C#实现导出List数据到xml文件的方法【附demo源码下载】

    这篇文章主要介绍了C#实现导出List数据到xml文件的方法,涉及C#针对list类及xml文件的相关操作技巧,并附带完整demo源码供读者下载参考,需要的朋友可以参考下...

    微wx笑4612021-12-03
  • C#WPF简单的数据库查询实例

    WPF简单的数据库查询实例

    下面小编就为大家分享一篇WPF简单的数据库查询实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    happy多乐4792022-02-12
  • C#C#开发简易winform计算器程序

    C#开发简易winform计算器程序

    这篇文章主要为大家详细介绍了C#开发简易winform计算器程序,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 ...

    WarrenHome7362022-02-20
  • C#C#获取U盘序列号的方法

    C#获取U盘序列号的方法

    这篇文章主要介绍了C#获取U盘序列号的方法,涉及C#针对硬件底层信息操作的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下...

    蓝图12462021-10-28
  • C#C#开发中的垃圾回收机制简析

    C#开发中的垃圾回收机制简析

    这篇文章主要为大家详细介绍了C#开发中的垃圾回收机制,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    C#教程网8082021-11-01
  • C#C#中的 == 和equals()区别浅析

    C#中的 == 和equals()区别浅析

    这篇文章主要介绍了C#中的 == 和equals()的区别,对不同点进行了阐述,感兴趣的小伙伴们可以参考一下...

    C#教程网10572021-11-01
  • C#常用C#正则表达式汇总介绍

    常用C#正则表达式汇总介绍

    c#正则表达式,用于字符串处理、表单验证等场合,实用高效。现将一些常用的表达式收集于此,以备不时之需。...

    C#教程网6632021-11-08