当前位置: 首页 > news >正文

C#高级 02异步编程

在这里插入图片描述

基础知识

1.什么是异步任务

  • 包含了异步任务的各种状态的一个引用类型
    1)正在运行、完成、结果、报错等
    2)另有ValueTask值类型版本
  • 对于异步任务的抽象
    1)开启异步任务后,当前线程并不会阻塞,而是可以去做其他事情
    2)异步任务(默认)会借助线程池在其他线程上运行
    3)获取结果后回到之前的状态
  • 任务结果
    1)返回值为Task的方法表示异步任务没有返回值
    2)返回值为Task则表示有类型为T的返回值

2.异步方法(async Task)

  • 将方法标记async后,可以在方法中使用await关键字
  • await关键字会等待异步任务,并获得结果
  • async+await会将方法包装成状态机,await类似于检查点(MoveNext方法会被底层调用,从而切换状态)
  • async Task
  • async void
  • 异步编程具有传染性

3.不阻塞

  • await会展示释放当前线程,使得该线程可以执行其他工作,而不必阻塞线程直到异步操作完成
  • 不要在异步方法里面用任何方式阻塞当前线程
  • 常见阻塞情况
    1)Task.Wait() & Task.Result()如果任务没有完成,则会阻塞当前线程,容易导致死锁
    2)Task.Delay() 是一个异步任务,会立刻释放当前线程
    3)Thread.Sleep() 会阻塞当前的线程,这与异步编程的理念不符
    4)IO等操作的同步方法
    5)其他繁重且耗时的任务

4.同步上下文

  • 一种管理和协调线程的机制,允许开发者将代码的执行切换到特定线程
  • WinForms 与 WPF 拥有同步上下文(UI线程),而控制台程序默认没有
  • ConfigureAwait(false)
    1)配置任务通过await方法结束后是否会到原来的线程,默认为true
    2)一般只有UI线程会采用这种策略
  • TaskScheduler
    1)控制Task的调度方式和运行线程
    1.1)线程池线程Default
    1.2)当前线程CurrentThread
    1.3)单线程上下文 STAThread
    1.4)长时间运行线程LongRunning
    2)优先级、上下文、执行状态等

5.一发即忘

  • 调用一个异步方法,但是并不使用await或阻塞的方式去等待它的结果
  • 无法观察任务状态(是否完成、是否报错等)

二.常见误区

1异步是否一定是多线程?

  • 异步编程不必需要多线程来实现(时间片轮转调度)
  • 比如可以在单个线程上使用异步I/O或事件驱动的编程模型(EAP)
  • 单线程异步:自己定好计时器,到时间之前先去做别的事
  • 多线程异步:将任务交给不同的线程,并由自己来进行指挥调度

2.异步方法一定要写成 async Task?

  • async关键字知识用来配合await使用,从而将方法包装成状态机
  • 本质上任然是Task,只不过提供了语法糖,并且函数体中可以直接return Task的泛型类型
  • 接口中无法声明async Task

3.await一定会切换同步上下文?

  • 在使用await关键字调用并等待一个异步任务时,异步方法不一定会立刻来到新的线程上
  • 如果 await 了一个已经完成的任务(包括Task.Delay(0)),会直接获得结果

4.异步编程可以取代多线程

  • 异步编程和多线程有一定关系,但是两者并不是可以完全相互代替的

5.Task.Result一定会阻塞当前线程?

  • 如果任务已经完成,那么Task.Result可以直接得到结果

6.开启的异步任务一定不会阻塞当前线程?

await关键字不一定会立刻释放当前线程,所以如果调用的异步方法中存在阻塞(如 Thread.Sleep(0)),那么依旧会阻塞当前线程上下文对应的线程

相关文章:

  • table表格中使用el-popover 无效问题解决
  • 连接progressql报错Cannot load JDBC driver class ‘org.postgresql.Driver‘,亲测有效!!!
  • 尝试读取挪威 3d radar数据
  • 年度总结 | 回味2023不平凡的一年
  • 一款超酷的一体化网站测试工具:Web-Check
  • Ubuntu Linux 入门指南:面向初学者
  • 父组件向子组件传递数据
  • 浅谈数据仓库运营
  • LeetCode 2706. 购买两块巧克力【数组,一次遍历】1207
  • P8780 [蓝桥杯 2022 省 B] 刷题统计
  • Java多线程之线程池,volatile,悲观锁,乐观锁,并发工具类
  • 机器学习之BP神经网络精讲(Backpropagation Neural Network(附案例代码))
  • 基于SpringBoot的在线互动学习网站
  • git上传代码到github远程仓库
  • 个人博客主题 vuepress-hope
  • 2017 前端面试准备 - 收藏集 - 掘金
  • Apache的基本使用
  • Go 语言编译器的 //go: 详解
  • Java 多线程编程之:notify 和 wait 用法
  • JavaScript 一些 DOM 的知识点
  • java中的hashCode
  • PHP 7 修改了什么呢 -- 2
  • Traffic-Sign Detection and Classification in the Wild 论文笔记
  • Vue实战(四)登录/注册页的实现
  • 基于OpenResty的Lua Web框架lor0.0.2预览版发布
  • 免费小说阅读小程序
  • 小程序开发中的那些坑
  • 学习HTTP相关知识笔记
  • 一个SAP顾问在美国的这些年
  • 一起来学SpringBoot | 第三篇:SpringBoot日志配置
  • 用 vue 组件自定义 v-model, 实现一个 Tab 组件。
  • 不要一棍子打翻所有黑盒模型,其实可以让它们发挥作用 ...
  • 策略 : 一文教你成为人工智能(AI)领域专家
  • 微龛半导体获数千万Pre-A轮融资,投资方为国中创投 ...
  • #mysql 8.0 踩坑日记
  • #pragma预处理命令
  • #传输# #传输数据判断#
  • (9)目标检测_SSD的原理
  • (论文阅读22/100)Learning a Deep Compact Image Representation for Visual Tracking
  • (一)使用IDEA创建Maven项目和Maven使用入门(配图详解)
  • (原創) 如何將struct塞進vector? (C/C++) (STL)
  • ..thread“main“ com.fasterxml.jackson.databind.JsonMappingException: Jackson version is too old 2.3.1
  • .NET Conf 2023 回顾 – 庆祝社区、创新和 .NET 8 的发布
  • .net core 微服务_.NET Core 3.0中用 Code-First 方式创建 gRPC 服务与客户端
  • .Net开发笔记(二十)创建一个需要授权的第三方组件
  • .vue文件怎么使用_我在项目中是这样配置Vue的
  • @RequestParam @RequestBody @PathVariable 等参数绑定注解详解
  • [ Algorithm ] N次方算法 N Square 动态规划解决
  • [.NET]桃源网络硬盘 v7.4
  • [20150904]exp slow.txt
  • [20171101]rman to destination.txt
  • [Android] Amazon 的 android 音视频开发文档
  • [C]编译和预处理详解
  • [docker] Docker的数据卷、数据卷容器,容器互联
  • [Gradle] 在 Eclipse 下利用 gradle 构建系统