【C#】ProgressBar进度条异步编程思想

1.控件介绍

进度条通常用于显示代码的执行进程进度,在一些复杂功能交互体验时告知用户进程还在继续。
在这里插入图片描述
在属性栏中,有三个值常用:
Value表示当前值,Minimum表示进度条范围下限,Maximum表示进度条范围上限。

2.简单实例

在一个界面下,点击按钮,进度条加载,用label显示运行耗时。
在这里插入图片描述

在Form1.cs中,添加点击Button1按钮功能:

private async void button1_Click(object sender, EventArgs e)
{Stopwatch stopwatch = new Stopwatch();stopwatch.Start();button1.Enabled = false;//防止重复点击progressBar1.Value = 0;int progressStep = 10;for (int i = 0; i <= progressBar1.Maximum; i = i + progressStep){await Task.Delay(100);progressBar1.Value = i;}button1.Enabled = true;stopwatch.Stop();label1.Text = $"运行耗时:{stopwatch.ElapsedMilliseconds}ms";MessageBox.Show("ok");
}

3.异步编程思想:

异步编程是一种编程范式,它允许程序在执行耗时操作时,不阻塞主线程或调用线程,从而提高程序的响应性和性能。简单来说,异步编程使得程序在等待某些操作(如网络请求、文件I/O、数据库查询等)的完成时,可以继续处理其他任务。

3.1 为什么需要异步编程?

在同步编程模式下,当程序执行一个耗时操作(例如读取文件或从网络获取数据)时,整个程序会暂停,主线程被堵塞,直到这个操作完成。这会导致程序变得不可响应,特别是在需要处理用户交互的应用程序中。
异步编程通过允许程序处理其他任务而不会被耗时操作阻塞,解决了这一问题。例如,在用户接口应用程序中,异步编程可以防止界面“卡死”,从而提升用户体验。

3.2 异步编程流程:

功能代码如下:模拟一个等待执行

private async Task LoadDataAsync()
{await Task.Delay(5000);  // 异步等待 5 秒Console.WriteLine("数据加载完成");  // 5 秒后执行
}

(1)当线程执行到await关键字标识的位置后,系统将方法挂起,返回控制权给调用者。
(2)任务调度器记录 Task.Delay(5000),在 5 秒后标记任务为完成。
(3)5秒后,任务调度器标记 Task.Delay(5000) 完成。调度器触发回调,通知方法恢复执行。打印"数据加载完成"。
(4)在挂起期间,用户可以自行操作,不会造成UI阻塞。

3.3 await是什么?

await是C#中的关键字,用于异步编程等待异步操作的完成,不会阻塞当前进程。通常与async关键字一起用。

3.4 async是什么?

async也是C#中的关键字,用于修饰方法、匿名函数或者lambda表达式。通常和await一起用,指示他们包含异步操作

3.5 Task是什么?

异步方法通常返回 Task 或 Task 对象,表示一个异步操作的进行。
Task 类还可以用于表示和管理异步操作。

以上三个关键字总结:async 修饰的方法通常返回 Task 或 Task < T >,而 await 用于等待任务的完成。

3.6 应用例子:

在图形用户界面(GUI)应用程序中,阻塞主线程会导致用户界面变得不可响应。例如,如果用户点击一个按钮触发一个耗时操作,整个界面会在操作完成之前冻结,无法响应用户的其他操作。
单纯摆出异步编程的例子无法体会精髓,先用一个同步编程的来对比:

同步编程:

点击button1按钮,开始执行功能代码,代码功能放到了另一个方法中去,该方法的功能就是单纯进行线程休眠,模拟耗时操作。

private void button1_Click(object sender, EventArgs e)
{Stopwatch stopwatch = new Stopwatch();stopwatch.Start();button1.Enabled = false;//防止重复点击Form1Bar.Value = 0;int progressStep = 10;for (int i = 0; i <= Form1Bar.Maximum; i = i + progressStep){// 同步方法,阻塞UI线程LoadData();Form1Bar.Value = i;}button1.Enabled = true;stopwatch.Stop();label1.Text = $"运行耗时:{stopwatch.ElapsedMilliseconds}ms";MessageBox.Show("ok");
}

模拟耗时方法:

private void LoadData()
{System.Threading.Thread.Sleep(1000);// 会强制阻塞线程
}

测试卡死按钮:

private void button2_Click(object sender, EventArgs e)
{textBox1.Text = "异步编程,UI未卡死";
}
private void button3_Click(object sender, EventArgs e)
{textBox1.Text = string.Empty;
}

在这里插入图片描述

运行过程中无法点击测试按钮,UI进程阻塞,GUI卡死。

异步编程(主窗口进度条):

异步编程会挂起当前await的耗时方法,不会阻塞当前线程,用户可以操作其他。

private async void button1_Click(object sender, EventArgs e)
{Stopwatch stopwatch = new Stopwatch();stopwatch.Start();button1.Enabled = false;//防止重复点击Form1Bar.Value = 0;int progressStep = 10;for (int i = 0; i <= Form1Bar.Maximum; i = i + progressStep){// 同步方法,阻塞UI线程await LoadData();Form1Bar.Value = i;}button1.Enabled = true;stopwatch.Stop();label1.Text = $"运行耗时:{stopwatch.ElapsedMilliseconds}ms";MessageBox.Show("ok");
}
private async Task LoadData()
{//System.Threading.Thread.Sleep(5000);// 会强制阻塞线程await Task.Delay(500);
}

在这里插入图片描述

异步编程(弹出窗口进度条):

Form1作为主界面,只放Button1和label1两个控件,点击开始后,弹出Form2进度条加载。
不仅实现弹出窗口进度条,还通过异步编程实现。
关键代码:

private async void button1_Click(object sender, EventArgs e)
{button1.Enabled = false;//防止重复点击Form2 form2 = new Form2();form2.Show();Stopwatch stopwatch = new Stopwatch();stopwatch.Start();for(int i = 0; i<= form2.Form2Bar.Maximum; i+= 10){await LoadData();form2.Form2Bar.Value = i;}button1.Enabled = true;stopwatch.Stop();label1.Text = $"运行耗时:{stopwatch.ElapsedMilliseconds}ms";MessageBox.Show("ok");form2.Close();
}
private async Task LoadData()
{await Task.Delay(500);
}

在这里插入图片描述

4.更进一步

仔细阅读上述代码可以发现,每次进度条加载是通过i来控制的,i每次随着休眠结束会自增10,这样确实可以均匀控制进度条增长。
但是现在有这样一个问题,在实际项目中,我们随着处理的数据量不同,并不知道每次运行的固定时间,换言之,可能并不是每次均匀增长一个固定值。

在之前先介绍一下一种特殊的函数-----回调函数

4.1 回调函数

回调函数,是指函数通过参数传给另一个函数,在满足特定的条件下由后者调用。
在异步编程思想中,当某个操作完成后,回调函数会被执行,处理或相应发生的事件。
下面是一个简单的代码展示:

// 定义一个回调函数
void CallbackFunction(string message)
{Console.WriteLine(message);
}// 定义一个异步函数,接受回调函数作为参数
void doSomethingAsync(Action<string> callback)
{// 模拟异步操作Task.Run(() =>{// 模拟一些工作Task.Delay(1000).Wait();// 调用回调函数callback("Operation completed!");});
}// 使用异步函数并传递回调函数
doSomethingAsync(CallbackFunction);

CallbackFunction(string message)是一个回调函数,当有字符串类型的参数传入时,会进行打印操作。
doSomethingAsync(Action callback)是一个异步函数(内部含有Task.Run),内部模拟了一个耗时异步操作,在结束后调用回调函数。

4.2 控制进度条

在不同任务耗时不一样的前提下,控制进度条的增长可以通过下面两种方法:
(1)将任务分解成为多个子任务,每个任务结束后手动增加,更新进度条。(看起来一卡一卡的)
(2)通过IProgress < T > 接口实现任务的进度报告,实时更新进度条。(进度均匀,更优雅)

两种方法其实很类似,都是需要去做一个标记,然后更新。

如果实在无法分割子任务,可使用进度条Marquee样式,实现类似跑马灯的效果,只告诉用户程序在运行,不知道结束的时间。

关键代码实例,只保留核心部分:
progress是一个报告器,接受参数,触发内部的Lambda回调函数,更新进度条。

private async void Button_Click(object sender, EventArgs e)
{// 创建一个进度报告器,更新进度条var progress = new Progress<int>(percent =>{progressBar.Value = percent; // 更新进度条});// 启动长时间运行的任务await ExecuteLongRunningTask(progress);// ...
}
private async Task ExecuteLongRunningTask(IProgress<int> progress)
{int totalSteps = 100; // 任务的总步数(假设任务可以分为100步)for (int i = 0; i < totalSteps; i++){// 模拟长时间任务await Task.Delay(100);  // 每步等待100毫秒// 报告进度progress.Report((i + 1) * 100 / totalSteps);}
}

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

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

相关文章

简单的git pull fail Can‘t update has no tracked branch解决记录

简单的git pull fail Can‘t update has no tracked branch解决记录 1. 问题描述 上午同事使用idea拉取代码的时候&#xff0c;发现拉取不了&#xff0c;提示用户权限问题&#xff0c;之后修改了git用户信息&#xff0c;发现还是拉取不了分支代码&#xff0c;然后删除了git r…

对FPGA开发流程系统的学习

FPGA 开发流程&#xff1a; HDL&#xff08;Hardware Design Language&#xff09;和原理图是两种最常用的数字硬件电路描述方法&#xff0c;HDL 设计法具有更好的可移植性、通用性和模块划分与重用性的特点&#xff0c;在目前的工程设计中被广泛使用。所以&#xff0c;我们在…

WPF在.NET9中的重大更新:Windows 11 主题

在2023年的2月20日&#xff0c;在WPF的讨论区&#xff0c;WPF团队对路线的优先级发起了一次讨论。 对三个事项发起了投票。 第一个是Windows 11 主题 第二个是更新的控件 第三个是可空性注释 最终Windows 11 主题得票最高&#xff0c;WPF团队2023-2024的工作优先级就是Windows…

网安小贴士(8)IPv4与IPv6

一、前言 IPv4和IPv6都是互联网协议&#xff08;IP&#xff09;的版本&#xff0c;它们用于在互联网上标识和定位设备。 二、定义 IPv4&#xff08;互联网协议第四版&#xff09;&#xff1a; IPv4是互联网协议的第一个广泛使用的版本&#xff0c;最初在1981年被标准化为RFC 7…

交换数字00

题目链接 交换数字 题目描述 注意点 numbers.length 2-2147483647 < numbers[i] < 2147483647 解答思路 不适用临时变量&#xff0c;可以先将numbers[0]和numbers[1]的信息都存到某个位置&#xff08;可以相加可以相减或其他位操作&#xff09;&#xff0c;然后另一…

SpringBoot 通过Knife4j集成API文档 在线调试

介绍 Knife4j 是一款基于 Swagger 构建的增强型 API 文档生成工具&#xff0c;它提供了更多的定制化功能和界面优化&#xff0c;使得生成的 API 文档更加美观和易用。它可以帮助开发者快速生成和管理 API 文档&#xff0c;支持在线调试和交互。 依赖 <!--knife4j--> &…

期末C语言易错知识点整理

1.在定义多维数组时&#xff0c;除了最左边的维度&#xff0c;其余的维度必须明确指定大小 2.int m[1][4]{4}; 定义的是一个 1 行 4 列的二维数组&#xff0c;初始化时提供了一个元素 4&#xff0c;其余元素默认初始化为 0&#xff0c;因此是正确的。 3.二维数组 a[3][6] 中的索…

谷粒商城学习笔记-05-项目微服务划分图

文章目录 一&#xff0c;商城业务服务-前端服务二&#xff0c;商城业务服务-后端服务三&#xff0c;存储服务四&#xff0c;第三方服务五&#xff0c;服务治理六&#xff0c;日志七&#xff0c;监控预警系统1&#xff0c;Prometheus2&#xff0c;Grafana3&#xff0c;Prometheu…

科技助力农业——土壤化肥测试仪

在农业生产中&#xff0c;土壤养分是作物健康生长的关键因素。然而&#xff0c;如何科学、精准地评估土壤养分含量&#xff0c;指导农民合理施肥&#xff0c;一直是农业科研和技术人员努力的方向。近年来&#xff0c;随着科技的进步&#xff0c;土壤化肥测试仪作为一种新型农业…

clion远程开发

clion远程开发 简要概括&#xff1a; 建立 SFTP 通讯&#xff0c;创建远程目录与本地目录的映射文件夹&#xff0c;就可以把本机文件夹中的文件用鼠标右键选中上全传&#xff0c;打开自动同步功能&#xff0c;后面更改文件就可以自动同步文件了。 一.新建SFTP远程链接服务 …

Unity游戏帧率查看软件Fraps

Download Fraps 3.5.99 free version 下载、安装、运行这个软件&#xff0c;左上角就会自动显示帧率

Java面试八股之MYISAM和INNODB有哪些不同

MYISAM和INNODB有哪些不同 MyISAM和InnoDB是MySQL数据库中两种不同的存储引擎&#xff0c;它们在设计哲学、功能特性和性能表现上存在显著差异。以下是一些关键的不同点&#xff1a; 事务支持&#xff1a; MyISAM 不支持事务&#xff0c;没有回滚或崩溃恢复的能力。 InnoDB…

通义千问 Qwen2,登顶国内第一大模型!

大家好&#xff0c;我是煎鱼。 7 月 9 日起&#xff0c;OpenAI 将正式终止对部分地区&#xff08;包含中国&#xff09;提供 API 服务&#xff0c;引起业内一片哗然&#xff0c;纷纷开始自检&#xff0c;找新的国内可用的国产化替代方案。 此时我有一个朋友的 Boss&#xff0c;…

【论文阅读】LLM+3D (1)

文章目录 1. 【CoRL 2023】SayPlan: Grounding Large Language Models using 3D Scene Graphs for Scalable Robot Task Planning动机摘要和结论引言模型框架3.1 Problem Formulation3.2 Preliminaries 2. ShapeLLM: Universal 3D Object Understanding for Embodied Interacti…

leetcode 403周赛 包含所有1的最小矩形面积||「暴力」

3197. 包含所有 1 的最小矩形面积 II 题目描述&#xff1a; 给你一个二维 二进制 数组 grid。你需要找到 3 个 不重叠、面积 非零 、边在水平方向和竖直方向上的矩形&#xff0c;并且满足 grid 中所有的 1 都在这些矩形的内部。 返回这些矩形面积之和的 最小 可能值。 注意…

Node.js的下载、安装和配置

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

返回值处理器器【Spring源码学习】

定义返回值类型处理器的组合&#xff1b; public static HandlerMethodReturnValueHandlerComposite getReturnValueHandler(){HandlerMethodReturnValueHandlerComposite composite new HandlerMethodReturnValueHandlerComposite();// 处理ModelAndViewcomposite.addHandle…

Elasticsearch实战教程:如何使用集群索引数据来进行统计多个数据?

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 引入 Elasticsearch聚合查询是一种强大的工具&#xff0c;允许我们对索引中的数据进行复杂的统计分析和计算。本文将详细解释一…

CFS三层内网渗透——外网打点(一)

目录 外网打点 先爆破一下看看有没有啥可进攻路径 尝试那个可疑的路径发现是thinkphp这个框架&#xff0c;同时也知道了版本&#xff0c;那就nday打吧 写入php ​编辑写入php成功&#xff0c;简简单单nday拿下​编辑 蚁剑rce尝试链接 打点成功 外网打点 先爆破一下看看有…

(自适应手机端)保健品健康产品网站模板下载

(自适应手机端)保健品健康产品网站模板下载PbootCMS内核开发的网站模板&#xff0c;该模板适用于装修公司网站、装潢公司网站等企业&#xff0c;当然其他行业也可以做&#xff0c;只需要把文字图片换成其他行业的即可&#xff1b;自适应手机端&#xff0c;同一个后台&#xff0…