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

c#异步编程(async/await)

注:下文摘自ChatGPT,总结与案例都非常完善,可以快速理解并应用

0:使用场景

在winform界面程序中,在ui操作中涉及到一些耗时的等待操作,使用线程自己处理已经显得力不从心,如何能更好的实现:能等待后台线程执行完,而且不阻塞UI。c#提供如下操作,高效满足此类应用场景,c++中同样有类似的用法(类似于QT线程间通信(信号槽))

1. 使用异步编程(async/await

最推荐的解决方法是使用 async/await,它可以将耗时操作放到后台线程运行,同时保持 UI 线程的响应。

示例:

场景:按钮点击后等待一个耗时任务完成,但界面仍可响应。
private async void Button_Click(object sender, EventArgs e)
{// 显示加载状态Button.Enabled = false;Label.Text = "Processing...";// 执行耗时操作await Task.Run(() => LongRunningTask());// 恢复 UILabel.Text = "Done!";Button.Enabled = true;
}// 模拟一个耗时任务
private void LongRunningTask()
{Thread.Sleep(5000); // 模拟耗时操作,实际中可替换为真实逻辑
}

原理

  • Task.Run 将耗时操作放到线程池中运行,不阻塞主线程。
  • await 确保任务完成后才继续执行,但不阻塞 UI 线程。

2. 使用 BackgroundWorker

BackgroundWorker 是较老的异步模式,但仍可用于一些简单场景。

示例:

private BackgroundWorker worker;public MainForm()
{InitializeComponent();worker = new BackgroundWorker();worker.DoWork += Worker_DoWork;worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
}private void Button_Click(object sender, EventArgs e)
{// 显示加载状态Button.Enabled = false;Label.Text = "Processing...";// 启动后台任务worker.RunWorkerAsync();
}private void Worker_DoWork(object sender, DoWorkEventArgs e)
{// 在后台线程中执行耗时操作Thread.Sleep(5000); // 模拟耗时操作
}private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{// 任务完成后更新 UILabel.Text = "Done!";Button.Enabled = true;
}

注意

  • DoWork 方法在后台线程中运行。
  • RunWorkerCompleted 方法在主线程(UI 线程)中运行,适合更新界面。

3. 使用 Task 和 Lambda

如果你不想使用 async/await,可以直接使用 Task 和回调来处理任务。

示例:

private void Button_Click(object sender, EventArgs e)
{// 显示加载状态Button.Enabled = false;Label.Text = "Processing...";Task.Run(() =>{// 在后台线程中执行耗时操作Thread.Sleep(5000); // 模拟耗时操作}).ContinueWith(t =>{// 回到主线程更新 UILabel.Text = "Done!";Button.Enabled = true;}, TaskScheduler.FromCurrentSynchronizationContext());
}

4. 使用 DispatcherInvoke

在 WPF 中,可以使用 Dispatcher 更新 UI;在 WinForms 中,可以使用 Invoke 方法。

示例(WinForms):

private void Button_Click(object sender, EventArgs e)
{Task.Run(() =>{// 耗时操作Thread.Sleep(5000);// 使用 Invoke 更新 UIthis.Invoke((Action)(() =>{Label.Text = "Done!";Button.Enabled = true;}));});// 立即禁用按钮(UI 线程)Button.Enabled = false;Label.Text = "Processing...";
}

5. 使用 Progress<T>(可选,报告进度)

如果耗时任务需要报告进度,可以使用 IProgress<T>Progress<T>

示例:

private async void Button_Click(object sender, EventArgs e)
{var progress = new Progress<int>(value =>{// 更新进度条ProgressBar.Value = value;});// 显示加载状态Button.Enabled = false;Label.Text = "Processing...";// 执行耗时任务并报告进度await Task.Run(() => LongRunningTaskWithProgress(progress));// 恢复 UILabel.Text = "Done!";Button.Enabled = true;
}private void LongRunningTaskWithProgress(IProgress<int> progress)
{for (int i = 0; i <= 100; i += 10){Thread.Sleep(500); // 模拟任务progress.Report(i); // 报告进度}
}

优点

  • 允许在任务进行过程中更新 UI(如进度条)。

6. 注意事项

  • 避免直接使用 Thread.Sleep 在主线程中运行:会导致 UI 完全无响应。
  • 耗时操作不要在 UI 线程中运行:始终将耗时逻辑放到后台线程。
  • 推荐使用现代的 async/await:代码更简洁且易于维护。

相关文章:

c#异步编程(async/await)

注&#xff1a;下文摘自ChatGPT&#xff0c;总结与案例都非常完善&#xff0c;可以快速理解并应用 0&#xff1a;使用场景 在winform界面程序中&#xff0c;在ui操作中涉及到一些耗时的等待操作&#xff0c;使用线程自己处理已经显得力不从心&#xff0c;如何能更好的实现&am…...

TCP/IP学习笔记

TCP\IP从实际应用的五层结构开始&#xff0c;自顶而下的去分析每一层。 TCP/IP五层架构概述 学术上面是TCP/IP四层架构&#xff0c;OSI/ISO是七层架构&#xff0c;实际中使用的是TCP/IP五层架构。 数据链路层 ICMP数据包分析 Wireshark抓包分析ICMP协议_wireshark抓ping包分析…...

0000_vim自定义快捷键_alias

vim自定义快捷键_alias 如下&#xff1a; 1.直接打开vi ~/.bashrc 然后到最底部&#xff0c;添加alias快捷键 2.添加alias快捷键mgplat 以后只要发送mgplat就等于出发了那么长一条指令 3.保存退出即可 【注意】 操作完后&#xff0c;可能你用mgplat无法使用&#xff0c;可…...

Spring Boot项目中,实体类是否需要实现Serializable接口

在Spring Boot项目中&#xff0c;实体类是否需要实现Serializable接口并不是一个硬性规定&#xff0c;而是取决于具体的应用场景和需求。以下是对这一问题的更详细分析&#xff1a; 1. 序列化的基本概念 序列化是将对象的状态信息转换为可以存储或传输的形式的过程。反序列化则…...

打通工业通信壁垒实现Ethernetip转profinet网络互通

西门子S7-1500 PLC&#xff08;profinet&#xff09;与AB PLC 1769-L32E以太网通讯&#xff08;EtherNet/IP&#xff09;。今天与大家分享一篇Profinet转EtherNet/IP的通讯配置方案。本文主要介绍开疆智能的Profinet转EtherNet/IP网关KJ-PNG-208&#xff0c;连接西门子S7-1500 …...

数据结构_图的应用

最小生成树 Prim算法 int AMGraph::sum(string v) {int start, totalW, cnt, minW, u, vv, i, j;start LocateVex(v); // 获取起始顶点编号memset(visited, false, sizeof(visited)); // 初始化访问状态visited[start] true;totalW 0; // 最小生成树的总权重cnt 1; // 当前…...

C#中面试的常见问题002

1.wpf和Winfrom的区别 1. 技术基础 WPF&#xff1a;基于.NET Framework&#xff0c;使用XAML&#xff08;可扩展应用程序标记语言&#xff09;作为界面描述语言&#xff0c;支持矢量图形和高级布局。WinForms&#xff1a;基于.NET Framework&#xff0c;使用纯代码或拖放设计…...

快速理解微服务中Ribbon的概念

一.基本概念 1.在微服务架构中&#xff0c;Ribbon 是一个客户端负载均衡器&#xff0c;用于控制服务间的通信方式。 2.Ribbon 是一个开源的库&#xff0c;最早由 Netflix 开发&#xff0c;用于实现客户端负载均衡。 3.Ribbon 主要解决的是在微服务架构中&#xff0c;多个服务…...

K8S简介、使用教程

以下是关于 Kubernetes&#xff08;通常缩写为 K8S&#xff09;的简介和使用教程&#xff1a; 一、Kubernetes 简介 定义与作用 Kubernetes 是一个开源的容器编排平台&#xff0c;用于自动化部署、扩展和管理容器化应用程序。它最初由谷歌开发&#xff0c;后捐赠给云原生计算基…...

极狐GitLab 17.6 正式发布几十项与 DevSecOps 相关的功能【四】

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 学习极狐GitLab 的相关资料&#xff1a; 极狐GitLab 官网极狐…...

麦肯锡报告 | 科技落地的真谛:超越技术本身的价值创造

科技创新正在以惊人的速度改变企业运作和客户体验&#xff0c;但实现其潜力的关键在于正确的策略、流程、文化和人才。麦肯锡强调了一个理念&#xff1a;Never just tech&#xff08;不仅仅是技术&#xff09;。这表明&#xff0c;成功的数字化转型不仅依赖于技术&#xff0c;还…...

彻底解决 macOS 下Matplotlib 中文显示乱码问题

彻底解决 macOS 下Matplotlib 中文显示乱码问题 在使用 Python 的 Matplotlib 库进行数据可视化时&#xff0c;中文字符的显示常常会出现乱码问题&#xff0c;尤其在 macOS 系统上。在网上找了一大堆方法&#xff0c;花了很久&#xff0c;发现不是要安装各种字体就是要改配置&…...

STM32-- keil 的option for target使用

keil版本号 1.device界面 如&#xff1a;stm32f103c8t6的工程&#xff0c;可以直接在device这里修改成stm32f103vct6&#xff0c;虽然引脚不一样&#xff0c;但是很多一样的地方&#xff0c;可以直接使用&#xff0c;有些不修改也可以下载程序。 2.target xtal的设置不起作用了…...

【MCU】微控制器的编程技术:ISP 与 IAP

在嵌入式领域中&#xff0c;将程序下载到内置 Flash 有两种技术 ISP (In-system programming) ISP 即在系统编程&#xff0c;是指一些可编程逻辑器件、微控制器、芯片组和其他嵌入式设备在安装到完整嵌入式系统后能够进行编程&#xff0c;而不需要在将芯片安装到系统中之前对…...

C#基础题总结

16.一张单据上有一个5位数的号码为6**42&#xff0c;其中百位数和千位数已模糊不清&#xff0c;但知道该数能被 57 和 67 除尽。设计一个算法&#xff0c;找出该单据所有可能的号码。 17.编程序求2&#xff5e;10000以内的完全数。一个数的因子&#xff08;除了这个数本身&…...

Elasticsearch中的节点(比如共20个),其中的10个选了一个master,另外10个选了另一个master,怎么办?

大家好&#xff0c;我是锋哥。今天分享关于【Elasticsearch中的节点&#xff08;比如共20个&#xff09;&#xff0c;其中的10个选了一个master&#xff0c;另外10个选了另一个master&#xff0c;怎么办&#xff1f;】面试题。希望对大家有帮助&#xff1b; Elasticsearch中的节…...

《参与中型项目,领略 Spring 魅力》

一、Spring 在中型项目中的魅力展现 Spring 框架以其强大的功能和灵活性&#xff0c;在中型项目中发挥着重要作用。它不仅简化了开发过程&#xff0c;还提高了代码的可维护性和可扩展性。 Spring 在中型项目中魅力十足&#xff0c;其优势主要体现在以下几个方面。 首先&#…...

计算机网络-GRE(通用路由封装协议)简介

昨天我们学习了VPN的基本概念&#xff0c;虚拟专用网络在当前企业总部与分支间广泛使用。常用的划分方法为基于协议层次有GRE VPN、IPSec VPN、L2TP VPN、PPTP VPN、SSL VPN等。其实我有考虑该怎么讲&#xff0c;因为在IP阶段好像虚拟专用网络讲得不深&#xff0c;在IE的阶段会…...

开源电话机器人产品的优点是什么?

开源电话机器人产品的优点是什么&#xff1f; 作者&#xff1a;开源呼叫中心系统 FreeIPCC&#xff0c;Github地址&#xff1a;https://github.com/lihaiya/freeipcc 开源电话机器人产品作为人工智能技术的一种应用&#xff0c;近年来在电销、客户服务等多个领域展现出了显著的…...

Spring Boot 集成 Knife4j 的 Swagger 文档

在开发微服务应用时&#xff0c;API 文档的生成和维护是非常重要的一环。Swagger 是一个非常流行的 API 文档工具&#xff0c;可以帮助我们自动生成 RESTful API 的文档&#xff0c;并提供了一个友好的界面供开发者测试 API。本文将介绍如何在 Spring Boot 项目中集成 Knife4j …...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

UE5 学习系列(三)创建和移动物体

这篇博客是该系列的第三篇&#xff0c;是在之前两篇博客的基础上展开&#xff0c;主要介绍如何在操作界面中创建和拖动物体&#xff0c;这篇博客跟随的视频链接如下&#xff1a; B 站视频&#xff1a;s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

django filter 统计数量 按属性去重

在Django中&#xff0c;如果你想要根据某个属性对查询集进行去重并统计数量&#xff0c;你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求&#xff1a; 方法1&#xff1a;使用annotate()和Count 假设你有一个模型Item&#xff0c;并且你想…...

反射获取方法和属性

Java反射获取方法 在Java中&#xff0c;反射&#xff08;Reflection&#xff09;是一种强大的机制&#xff0c;允许程序在运行时访问和操作类的内部属性和方法。通过反射&#xff0c;可以动态地创建对象、调用方法、改变属性值&#xff0c;这在很多Java框架中如Spring和Hiberna…...

C++中string流知识详解和示例

一、概览与类体系 C 提供三种基于内存字符串的流&#xff0c;定义在 <sstream> 中&#xff1a; std::istringstream&#xff1a;输入流&#xff0c;从已有字符串中读取并解析。std::ostringstream&#xff1a;输出流&#xff0c;向内部缓冲区写入内容&#xff0c;最终取…...

【笔记】WSL 中 Rust 安装与测试完整记录

#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统&#xff1a;Ubuntu 24.04 LTS (WSL2)架构&#xff1a;x86_64 (GNU/Linux)Rust 版本&#xff1a;rustc 1.87.0 (2025-05-09)Cargo 版本&#xff1a;cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...

《Offer来了:Java面试核心知识点精讲》大纲

文章目录 一、《Offer来了:Java面试核心知识点精讲》的典型大纲框架Java基础并发编程JVM原理数据库与缓存分布式架构系统设计二、《Offer来了:Java面试核心知识点精讲(原理篇)》技术文章大纲核心主题:Java基础原理与面试高频考点Java虚拟机(JVM)原理Java并发编程原理Jav…...

HTTPS证书一年多少钱?

HTTPS证书作为保障网站数据传输安全的重要工具&#xff0c;成为众多网站运营者的必备选择。然而&#xff0c;面对市场上种类繁多的HTTPS证书&#xff0c;其一年费用究竟是多少&#xff0c;又受哪些因素影响呢&#xff1f; 首先&#xff0c;HTTPS证书通常在PinTrust这样的专业平…...

Appium下载安装配置保姆教程(图文详解)

目录 一、Appium软件介绍 1.特点 2.工作原理 3.应用场景 二、环境准备 安装 Node.js 安装 Appium 安装 JDK 安装 Android SDK 安装Python及依赖包 三、安装教程 1.Node.js安装 1.1.下载Node 1.2.安装程序 1.3.配置npm仓储和缓存 1.4. 配置环境 1.5.测试Node.j…...

Python的__call__ 方法

在 Python 中&#xff0c;__call__ 是一个特殊的魔术方法&#xff08;magic method&#xff09;&#xff0c;它允许一个类的实例像函数一样被调用。当你在一个对象后面加上 () 并执行时&#xff08;例如 obj()&#xff09;&#xff0c;Python 会自动调用该对象的 __call__ 方法…...