C#5.0-原生异步编程方式

简介: 微软提供的最新的异步编程基础设施。它允许我们以模块化的方式设计程序,来组合不同的异步操作。

带着问题去思考!大家好

简介


微软提供的最新的异步编程基础设施。它允许我们以模块化的方式设计程序,来组合不同的异步操作。

1:遗憾的是,当阅读此类程序时仍然非常难理解程序实际执行顺序。很多大型的程序中将会有许多相互依赖的任务和后续操作,处理异常的后续操作,并且它们都会出现在程序代码中的不同地方,因此了解程序的先后执行次序很难。

2:能够接触用户界面控制的每个异步任务是否得到了正确的同步上下文。程序只允许通过UI线程使用这些控制器,否则将会得到多线程的访问异常。说到异常,我们不得不使用单独的后续操作任务来处理在之前的异步操作中发生的错误。这又导致分散在代码的不同部分的复杂的处理错误的代码。逻辑无法相互关联。

C#5.0引入了新的语言特性。异步函数,它是TPL之上的更高级别的抽象。真正简化了异步编程。

须知:

  • 创建一个异步函数,首先需要用async关键字标注一个方法。
  • 异步函数必须返回Task或Task<T>类型,可以使用async void 方法,但是更推荐使用async task方法,
  • 使用async标注的方法内部,可以使用await操作符,该操作符可与TPL的任务一起工作,并获取该任务中异步操作的结果。
  • 异步函数在其代码中至少拥有一个await操作符。(没有则只是警告)
  • 不能在catch,finally,lock或unsafe代码块中使用await操作符。
  • 不允许对任何异步函数使用ref或out参数。

如果程序中有两个连续await操作符,他们是顺序运行的,第一个完成后第二个才会开始运行

 

使用await操作符获取异步任务结果

View Code

image.png

这里需要注意的是Task.Wait和Task.Result方法,如果不是百分百知道代码是干什么的,很容易造成死锁。

对连续的异步任务使用await操作符

View Code

同样运行两个异步操作,首先AsynchronyWithAwait方法将讲,这里使用了两个await声明,最重要一点是该代码是顺序执行,阅读代码很清晰,但是该程序如何是异步程序呢?首先,他不总是异步的,当使用await时如果一个任务已经完成,我们会异步地得到该任务结果。否则,当代码中看到await声明时,通常的行为是方法执行到该await代码行时将立即返回,并且剩下的的代码将会在一个后续操作任务中运行,因此等待操作结果时并没有阻塞程序执行。这是一个异步调用。

异步并不总是意味着并行执行。

对并行执行的异步任务使用await操作符

View Code

这里定义了两个异步任务,分别执行了3秒和5秒。然后使用了Task.WhenAll辅助方法创建另一个任务,该任务只有在所有底层任务完成后才运行,之后我们等待该组合任务的结果。这里两个任务似乎是被线程池中的同一个线程执行的。

两个任务被不同的工作线程执行,不同之处在于Task.Delay在幕后使用了一个计时器,从线程池中获取工作线程,它将等待Task.Delay方法返回结果。然后,Task.Delay方法启动计时器并指向一块代码,该代码会在计时器时间到了Task.Delay方法中指定的秒数后被调用。之后即将工作线程返回到线程池中。当计时器事件运行时,我们又从线程池中任意获取一个可用的工作线程(可能就是运行一个任务时使用的线程

当使用Task.Run方法时,从线程池中获取一个工作线程并将其阻塞几秒,具体秒数由Thread.Sleep方法提供。然后获取了第二个。 工作线程并且将其阻塞。在这种场景下,我们消费了两个工作线程,而它们绝对什么事没做,因为在它们等待时不能执行任何其他操作。

 

处理异步操作中的异常

View Code

这里实现了三个场景来展示在C#中使用async和await时关于错误处理的最常见情况,一种情况最简单,与同步代码几乎一样,使用try/catch声明即可获取异常细节。一种很常见的错误是对一个以上的异步操作使用await时还使用以上方式。如果跟第一种处理的话,则只能从底层的AggregateException对象中得到第一个异常。为了收集所有异常信息,可以使用await任务的Exception属性,在第三种情况中,我们使用AggregateException的Flatten方法将层级异常放入一个列表,并且从中提取出所有的底层异常。

相关文章
|
6月前
|
C# 开发者
深入理解C#中的`Task<T>`:异步编程的核心
【1月更文挑战第3天】本文旨在探讨C#中`Task<T>`的使用和理解,作为异步编程模式的核心组件。`Task<T>`允许开发者在不阻塞主线程的情况下执行异步操作,并返回一个指定类型`T`的结果。通过定义返回`Task<T>`的异步方法、使用`async`和`await`关键字、处理异常以及获取任务结果,开发者可以编写出高效且响应迅速的应用程序。此外,本文还介绍了如何配置任务以及实现任务的连续性和组合,为掌握C#中的异步编程提供了全面的指导。
|
2月前
|
C# UED
C#一分钟浅谈:异步编程基础 (async/await)
在现代软件开发中,异步编程对于提升应用性能和响应性至关重要,尤其是在处理网络请求和文件读 异步编程允许程序在等待操作完成时继续执行其他任务,从而提高用户体验、高效利用资源,并增强并发性。在 C# 中,`async` 用于标记可能包含异步操作的方法,而 `await` 则用于等待异步操作完成。 示例代码展示了如何使用 `async` 和 `await` 下载文件而不阻塞调用线程。此外,本文还讨论了常见问题及解决方案,如不在 UI 线程上阻塞、避免同步上下文捕获以及正确处理异常。
48 0
|
C#
C#异步编程
C#异步编程
183 0
|
C#
c#异步编程
c#异步编程原理,await asnyc的使用方法。异步编程是指在程序执行过程中,不需要等待某个操作完成,就可以继续执行后续的代码。
299 0
|
C#
C#网络应用编程,实验七: 异步编程练习
C#网络应用编程,实验七: 异步编程练习
119 1
C#网络应用编程,实验七: 异步编程练习
|
C#
C#网络应用编程,异步编程基础练习
C#网络应用编程,异步编程基础练习
147 1
C#网络应用编程,异步编程基础练习
|
Java .NET C#
C#并发编程之异步编程(线程讨论)
C#并发编程之异步编程(线程讨论)写在前面本篇是异步编程系列的第三篇,本来计划第三篇的内容是介绍异步编程中常用的几个方法,但是前两篇写出来后,身边的朋友总是会有其他问题,所以决定在续写一篇,作为异步编程(一)和异步编程(二)的补充。
1454 0
|
C# 编译器 数据库
C#并发编程之异步编程(二)
C#并发编程之异步编程(二)写在前面前面一篇文章介绍了异步编程的基本内容,同时也简要说明了async和await的一些用法。本篇文章将对async和await这两个关键字进行深入探讨,研究其中的运行机制,实现编码效率与运行效率的提升。
1418 0
C#并发编程之异步编程(一)
C#并发编程之异步编程(一) 写在前面       C#5.0中,对异步编程进行了一次革命性的重构,引入了async和await这两个关键字,使得开发人员在不需要深刻了解异步编程的底层原理,就可以写出十分优美而又代码量极少的代码。
1408 0