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:代码更简洁且易于维护。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/60974.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux环境变量(添加环境变量、修改系统环境变量、内建命令和非内建命令)

Linux环境变量&#xff08;添加环境变量、修改系统环境变量、内建命令和非内建命令&#xff09; 1. 环境变量的介绍 环境变量&#xff08;environment variables&#xff09;一般是指在操作系统中用来指定操作系统运行环境的一些参数。环境变量是在操作系统中一个具有特定名字…

Python 3 教程第2篇(基础语法)

编码 默认情况下&#xff0c;Python 3 源码文件以 UTF-8 编码&#xff0c;所有字符串都是 unicode 字符串。 当然你也可以为源码文件指定不同的 编码&#xff1a; # -*- coding: cp-1252 -*-上述定义允许在源文件中使用 Windows-1252 字符集中的字符编码&#xff0c;对应适合语…

排序算法之插入排序篇

插入排序 思路&#xff1a; 就是将没有排序的元素逐步地插入到已经排好序的元素后面&#xff0c;保持元素的有序 视频的实现过程如下&#xff1a; 插入排序全过程 代码实现过程如下&#xff1a; public static void Insertion(int[] arr) { for (int i 1; i < arr.length…

AVL、B树和B+树

AVL树定义 AVL树&#xff08;Adelson-Velsky 和 Landis 树&#xff09;是一种自平衡的二叉搜索树&#xff08;Binary Search Tree, BST&#xff09;&#xff0c;由苏联数学家Georgy Adelson-Velsky和Evgenii Landis在1962年提出。AVL树通过在每个节点上维护一个平衡因子&#…

Unity ShaderLab 实现3D物体描边

实现思路&#xff1a; 给物体添加第二个材质球&#xff0c;在shader的顶点着色器中使顶点的位置变大&#xff0c;然后在片元着色器中输出描边颜色。 shader Graph实现如下&#xff1a; ShaderLab实现如下&#xff1a; Shader "Custom/Outline" {Properties{[HDR]_…

【C++第三方库】Muduo库结合ProtoBuf库搭建服务端和客户端的过程和源码

每日激励&#xff1a;“不设限和自我肯定的心态&#xff1a;I can do all things。 — Stephen Curry” 绪论​&#xff1a; 本章我将结合之前的这俩个第三方库快速上手protobuf序列化和反序列化框架和muduo网络&#xff0c;来去实现muduo库在protocol协议搭建服务端和客户端。…

Jenkins的使用

文章目录 一、Jenkins是什么\有什么用\与GitLab的对比二、Jenkins的安装与配置Jenkins的安装方式在Linux上安装Jenkins&#xff1a;在Windows上安装Jenkins&#xff1a;配置Jenkins&#xff1a; &#xff08;可选&#xff09;配置启动用户为root&#xff08;一定要是root吗??…

Qml-TabBar类使用

Qml-TabBar类使用 TabBar的概述 TabBar继承于Container 由TabButton进行填充&#xff0c;可以与提供currentIndex属性的任何容器或布局控件一起使用&#xff0c;如StackLayout 或 SwipeView&#xff1b;contentHeight : real:TabBar的内容高度&#xff0c;用于计算标签栏的隐…

Cyberchef 辅助网络安全运营-数据格式转换

在网络安全的世界中&#xff0c;经常会遇到各种格式的数据&#xff0c;比如二进制&#xff0c;比如说16进制&#xff0c;URL编码&#xff0c;HTML编码&#xff0c;Unicode编码&#xff0c;Base格式的编码。网络安全运营一个明确的目标就是把这些不同的数据格式换成为可读的字符…

C语言——指针初阶(一)

目录 一.什么是指针&#xff1f;&#xff1f;&#xff1f; 指针是什么&#xff1f; 指针变量&#xff1a; 总结&#xff1a; 总结&#xff1a; 二.指针和指针类型 指针-整数&#xff1a; 总结&#xff1a; 指针的解引用 总结&#xff1a; 三.野指针 如何规避野指针 往期…

Tcon技术和Tconless技术介绍

文章目录 TCON技术&#xff08;传统时序控制器&#xff09;定义&#xff1a;主要功能&#xff1a;优点&#xff1a;缺点&#xff1a; TCONless技术&#xff08;无独立时序控制器&#xff09;定义&#xff1a;工作原理&#xff1a;优点&#xff1a;缺点&#xff1a; TCON与TCONl…

World of Warcraft /script SetRaidTarget(“target“, n, ““) n=8,7,6,5,4,3,2,1,0

魔兽世界执行当前目标标记方法 /script SetRaidTarget("target", n, "") n8,7,6,5,4,3,2,1,0 解析这个lua脚本 D:\Battle.net\World of Warcraft\_classic_\Interface\AddOns\wMarker wMarker.lua /script SetRaidTarget("target", 8, &quo…

学习笔记035——MySQL索引

数据库索引 索引是为了提高数据的查询速度&#xff0c;相当于给数据进行编号&#xff0c;在查找数据的时候就可以通过编号快速找到对应的数据。 索引内部数据结构&#xff1a;B Tree 主键自带索引。 如&#xff1a; insert into user (id, name) values (1,f); insert int…

在Unity中实现物体动画的完整流程

在Unity中&#xff0c;动画是游戏开发中不可或缺的一部分。无论是2D还是3D游戏&#xff0c;动画都能为游戏增添生动的视觉效果。本文将详细介绍如何在Unity中为物体添加动画&#xff0c;包括资源的准备、播放组件的添加、动画控制器的创建以及动画片段的制作与调度。 1. 准备动…

Python数据分析实例五、US 大选捐款数据分析

美国联邦选举委员会 (FEC) 公布了对政治竞选活动的贡献数据。这包括投稿人姓名、职业和雇主、地址和投款金额。2012 年美国总统大选的贡献数据以单个 150 MB 的 CSV 文件P00000001-ALL.csv形式提供,该文件可以通过以下pandas.read_csv加载: import pandas as pdfec = pd.r…

网络命令Linux

目录 一&#xff0c;Linux 二&#xff0c;CMD 一&#xff0c;Linux ping www.baidu.com 测试联网 -c 2 次数&#xff0c;ping几次 &#xff0c; -i 间隔 -W timeout 超时时间&#xff0c;等待响应的超时时间 ss -lntup |grep -w 22 netstat -lntup |grep -w 22 lsof -i:22 ls…

vue3项目搭建-3-Pinia的使用

Pinia 是集中状态管理工具 基本用法 Pinia 是 Vue 的专属的最新状态管理库&#xff0c;是 Vuex 状态管理工具的替代品 官方文档&#xff1a;pinia官方文档 找到开始目录&#xff0c;根据文档安装和入门 pinia&#xff0c;启用一个新的终端&#xff0c;输入指令 npm install…

docker部署的服务器数据备份

需要备份的数据可以分为三类 数据库文件volumes文件夹挂载volumes具名挂载 下面将针对三类数据具体描述备份方法 数据库文件 进入mysql容器中 docker exec it containerName /bin/bashcontainerName &#xff1a;mysql容器的名称 导出数据 mysgldump -u userName -p dbNa…

Flink Standalone 集群模式安装部署教程

目录 一、前言 二、环境准备 三、安装步骤 1. 下载并安装 Flink 4. 配置 Flink 5. 配置环境变量 6. 启动 Flink 集群 7. 访问 Flink Web 界面 四、简单测试 五、常见问题和解决办法 1. 启动失败&#xff0c;无法连接到 TaskManager 2. Web 界面无法访问 六、总结 …

Spring Boot 开发环境搭建详解

下面安装spring boot的详细步骤&#xff0c;涵盖了从安装 JDK 和 Maven 到创建和运行一个 Spring Boot 项目的全过程。 文章目录 1. 安装 JDK步骤 1.1&#xff1a;下载 JDK步骤 1.2&#xff1a;安装 JDK步骤 1.3&#xff1a;配置环境变量 2. 安装 Maven步骤 2.1&#xff1a;下载…