【WinForm.NET开发】实现使用后台操作的窗体

本文内容

  1. 创建使用后台操作的窗体
  2. 使用设计器创建 BackgroundWorker
  3. 添加异步事件处理程序
  4. 添加进度报告和取消支持
  5. Checkpoint

如果某项操作需要很长的时间才能完成,并且不希望用户界面 (UI) 停止响应或阻塞,则可以使用 BackgroundWorker 类在另一个线程上执行此操作。

本演练演示如何使用 BackgroundWorker 类“在后台”执行耗时的计算,同时用户界面保持响应。 演练时,将有一个异步计算 Fibonacci 数列的应用程序。 即使计算大型 Fibonacci 数列需要花费大量时间,但主 UI 线程不会被这种延时中断,并且在计算期间窗体仍会响应。

本演练涉及以下任务:

  • 创建基于 Windows 的应用程序

  • 在窗体中创建 BackgroundWorker

  • 添加异步事件处理程序

  • 添加进度报告和取消支持

1、创建使用后台操作的窗体

  1. 在 Visual Studio 中,创建一个名为 BackgroundWorkerExample 的基于 Windows 的应用程序项目(“文件”>“新建”>“项目”>“Visual C#”或“Visual Basic”>“经典桌面”>“Windows 窗体应用程序”)。

  2. 在“解决方案资源管理器”中,右键单击“Form1”,然后从快捷菜单中选择“重命名”。 将文件名更改为 FibonacciCalculator。 询问是否希望重命名对代码元素“”的所有引用时,单击“是”Form1按钮。

  3. 从“工具箱”将 NumericUpDown 控件拖到窗体上。 将 Minimum 属性设置为 1,将 Maximum 属性设置为 91

  4. 向窗体添加两个 Button 控件。

  5. 重命名第一个 Button 控件 startAsyncButton,并将 Text 属性设置为 Start Async。 重命名第二个 Button 控件 cancelAsyncButton,并将 Text 属性设置为 Cancel Async。 将它的 Enabled 属性设置为 false

  6. 为两个 Button 控件的 Click 事件创建一个事件处理程序。 

  7. 从“工具箱”将 Label 控件拖到窗体上,然后将其重命名为 resultLabel

  8. 从“工具箱”将 ProgressBar 控件拖到窗体上。

2、使用设计器创建 BackgroundWorker

可以使用“Windows 窗体设计器”为异步操作创建 BackgroundWorker。

从“工具箱”的“组件”选项卡中,将 BackgroundWorker 拖到窗体上。

3、添加异步事件处理程序

现在已准备好为 BackgroundWorker 组件的异步事件添加事件处理程序。 这些事件处理程序将调用在后台运行的计算 Fibonacci 数列的耗时操作。

  1. 在“属性”窗口中的 BackgroundWorker 组件仍处于选中状态时,单击“事件”按钮。 双击 DoWork 和 RunWorkerCompleted 事件以创建事件处理程序。 

  2. 在窗体中新建一个名为 ComputeFibonacci 的新方法。 此方法完成实际的工作,并在后台运行。 这些代码演示了 Fibonacci 算法的递归实现,这种算法的效率非常低,对于较大的数值花费的时间按指数增长。 在这里使用是出于演示的目的,为了说明在应用程序中某项操作可能带来长时间的延迟。

    // This is the method that does the actual work. For this
    // example, it computes a Fibonacci number and
    // reports progress as it does its work.
    long ComputeFibonacci(int n, BackgroundWorker worker, DoWorkEventArgs e)
    {// The parameter n must be >= 0 and <= 91.// Fib(n), with n > 91, overflows a long.if ((n < 0) || (n > 91)){throw new ArgumentException("value must be >= 0 and <= 91", "n");}long result = 0;// Abort the operation if the user has canceled.// Note that a call to CancelAsync may have set// CancellationPending to true just after the// last invocation of this method exits, so this// code will not have the opportunity to set the// DoWorkEventArgs.Cancel flag to true. This means// that RunWorkerCompletedEventArgs.Cancelled will// not be set to true in your RunWorkerCompleted// event handler. This is a race condition.if (worker.CancellationPending){e.Cancel = true;}else{if (n < 2){result = 1;}else{result = ComputeFibonacci(n - 1, worker, e) +ComputeFibonacci(n - 2, worker, e);}// Report progress as a percentage of the total task.int percentComplete =(int)((float)n / (float)numberToCompute * 100);if (percentComplete > highestPercentageReached){highestPercentageReached = percentComplete;worker.ReportProgress(percentComplete);}}return result;
    }
    
  3. 在 DoWork 事件处理程序中,添加对 ComputeFibonacci 方法的调用。 从 DoWorkEventArgs 的 Argument 属性中获取 ComputeFibonacci 的第一个参数。 稍后将 BackgroundWorker 和 DoWorkEventArgs 参数用于进度报告和取消支持。 将 ComputeFibonacci 的返回值分配给 DoWorkEventArgs 的 Result 属性。 此结果将可供 RunWorkerCompleted 事件处理程序使用。

     备注

    DoWork 事件处理程序不直接引用 backgroundWorker1 实例变量,因为这将会使此事件处理程序和某个特定的 BackgroundWorker 实例耦合。 相反,引发此事件的 BackgroundWorker 引用将从 sender 参数恢复。 当窗体承载多个 BackgroundWorker 时这非常重要。 在 DoWork 事件处理程序中不操作任何用户界面对象也非常重要。 而应该通过 BackgroundWorker 事件与用户界面进行通信。

    // This event handler is where the actual,
    // potentially time-consuming work is done.
    private void backgroundWorker1_DoWork(object sender,DoWorkEventArgs e)
    {// Get the BackgroundWorker that raised this event.BackgroundWorker worker = sender as BackgroundWorker;// Assign the result of the computation// to the Result property of the DoWorkEventArgs// object. This is will be available to the// RunWorkerCompleted eventhandler.e.Result = ComputeFibonacci((int)e.Argument, worker, e);
    }
    
  4. 在 startAsyncButton 控件的 Click 事件处理程序中,添加启动异步操作的代码。

    private void startAsyncButton_Click(System.Object sender,System.EventArgs e)
    {// Reset the text in the result label.resultLabel.Text = String.Empty;// Disable the UpDown control until// the asynchronous operation is done.this.numericUpDown1.Enabled = false;// Disable the Start button until// the asynchronous operation is done.this.startAsyncButton.Enabled = false;// Enable the Cancel button while// the asynchronous operation runs.this.cancelAsyncButton.Enabled = true;// Get the value from the UpDown control.numberToCompute = (int)numericUpDown1.Value;// Reset the variable for percentage tracking.highestPercentageReached = 0;// Start the asynchronous operation.backgroundWorker1.RunWorkerAsync(numberToCompute);
    }
    
  5. 在 RunWorkerCompleted 事件处理程序中,将计算结果分配给 resultLabel 控件。

    // This event handler deals with the results of the
    // background operation.
    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {// First, handle the case where an exception was thrown.if (e.Error != null){MessageBox.Show(e.Error.Message);}else if (e.Cancelled){// Next, handle the case where the user canceled// the operation.// Note that due to a race condition in// the DoWork event handler, the Cancelled// flag may not have been set, even though// CancelAsync was called.resultLabel.Text = "Canceled";}else{// Finally, handle the case where the operation// succeeded.resultLabel.Text = e.Result.ToString();}// Enable the UpDown control.this.numericUpDown1.Enabled = true;// Enable the Start button.startAsyncButton.Enabled = true;// Disable the Cancel button.cancelAsyncButton.Enabled = false;
    }
    

4、添加进度报告和取消支持

由于异步操作将会花费很长的时间,因此通常希望向用户报告进度并允许用户取消操作。 BackgroundWorker 类提供一个在后台操作进行时允许发送进度消息的事件。 它还提供允许辅助代码检测对 CancelAsync 的调用并中断自身的标记。

实现进度报告

  1. 在“属性”窗口中,选择 backgroundWorker1。 将 WorkerReportsProgress 和 WorkerSupportsCancellation 属性设置为 true

  2. 在 FibonacciCalculator 窗体中声明两个变量。 这将用于跟踪进度。

    private int numberToCompute = 0;
    private int highestPercentageReached = 0;
    
  3. 为 ProgressChanged 事件添加事件处理程序。 在 ProgressChanged 事件处理程序中,使用 ProgressChangedEventArgs 参数的 ProgressPercentage 属性更新 ProgressBar。

    // This event handler updates the progress bar.
    private void backgroundWorker1_ProgressChanged(object sender,ProgressChangedEventArgs e)
    {this.progressBar1.Value = e.ProgressPercentage;
    }
    

实现取消支持

  1. 在 cancelAsyncButton 控件的 Click 事件处理程序中,添加取消异步操作的代码。

    private void cancelAsyncButton_Click(System.Object sender,System.EventArgs e)
    {// Cancel the asynchronous operation.this.backgroundWorker1.CancelAsync();// Disable the Cancel button.cancelAsyncButton.Enabled = false;
    }
    
  2. 下面的 ComputeFibonacci 方法中的代码片段可报告进程并支持取消。

    if (worker.CancellationPending)
    {e.Cancel = true;
    }
    
    // Report progress as a percentage of the total task.
    int percentComplete =(int)((float)n / (float)numberToCompute * 100);
    if (percentComplete > highestPercentageReached)
    {highestPercentageReached = percentComplete;worker.ReportProgress(percentComplete);
    }
    

5、Checkpoint

此时,可以编译并运行 Fibonacci 计算器应用程序。

按 F5 编译并运行应用程序。

在后台运行计算的同时,将会看到 ProgressBar 显示完成计算的进度。 也可以取消挂起的操作。

对于较小数值,计算应非常快,但对于较大数值,将看到明显的延时。 如果输入 30 或更大的值,应看到有几秒钟的延时,这取决于计算机的速度。 对于大于 40 的值,完成计算可能要花费数分钟或数小时。 在计算器计算较大的 Fibonacci 数列时,注意可以自由地移动窗体、最小化、最大化甚至关闭窗体。 这是因为主 UI 线程不会等待计算完成。

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

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

相关文章

为什么C++17要引入std::string_view?

目录 1.引言 2.原理分析 2.1.结构 2.2.构造函数 2.3.成员函数 2.4.std::string_view字面量 3.实例 3.1.std::string_view和std::string的运算符操作 3.2.查找函数使用 3.3.std::string_view和临时字符串 4.总结 1.引言 在C/C日常编程中&#xff0c;我们常进行数据的…

JDK8新增的时间类

目录 内容大纲&#xff1a; 1、Zoneld时区 2、Instant时间戳 3、ZoneDateTime带时区的时间 4、DateTimeFormatter用于时间的格式化和解析 5、Calendar类&#xff1a; 6、工具类 内容大纲&#xff1a; 1、Zoneld时区 方法名说明static Set<String>getArailableZoneIds()获…

java集合(4)

1.HashSet集合 1.1HashSet集合概述和特点【应用】 底层数据结构是哈希表 存取无序 不可以存储重复元素 没有索引,不能使用普通for循环遍历 1.2HashSet集合的基本应用【应用】 存储字符串并遍历 public class HashSetDemo {public static void main(String[] args) {//创…

MCU常用外设总线

目录 前言一、时钟与中断二、GPIO三、ADC四、定时器4.1 基本定时器4.2 通用定时器4.2.1 输入捕获4.2.2 输出比较 五、UART六、IIC七、SPI 前言 本文主要讲单片机外设的功能&#xff0c;即这些外设是什么&#xff0c;可以用来干什么&#xff0c;了解了之后我们就可以通过相应的寄…

学校服务器hpc东南大学,下载国家基因组科技中心数据 gsa-human ascp chatpt建议 Linux系统中写代码

使用ascp批量下载数据 You files.csv 帮我写个批量下载的脚本&#xff0c;批量下载时候&#xff0c;把路径中最后的HRR659816批量替换成 Accession列的内容就行了。下面是示例 ascp -v -QT -l 300m -P33001 -k1 -i ~/.aspera/connect/etc/aspera01.openssh_for_gsa -d asper…

前端 解析压缩包,并且读取Shp生成GeoJson在MapBox上渲染

这里需要先安装shapefile&#xff1b;jszip;turf npm install shapefile npm install jszip npm install turf/turf <ElUploadref"upload"v-model:file-list"fileListShp":limit"1"accept".zip":show-file-list"true":au…

算法训练day18Leetcode找树左下角的值112路径总和106从中序和后续遍历构造二叉树

513 找树左下角的值 题目描述 给定一个二叉树的 根节点 root&#xff0c;请找出该二叉树的 最底层 最左边 节点的值。假设二叉树中至少有一个节点。示例 1:输入: root [2,1,3] 输出: 1 示例 2:输入: [1,2,3,4,null,5,6,null,null,7] 输出: 7提示:二叉树的节点个数的范围是 […

贝锐蒲公英云AP体验:云端快速部署、远程管理,轻松满足办公环境

公司原本的网络由于采用多个路由器&#xff0c;导致无线信号杂乱&#xff0c;管理不便&#xff0c;且远程办公体验较差&#xff0c;作为IT负责人的我&#xff0c;一直想寻找一个可以实现网络统一管理并有效提升远程工作便捷性的产品。 于是&#xff0c;我决定在公司内部部署贝…

5G_射频测试_基础概念(二)

定义了测试参考点&#xff0c;不同的RRU类型 C类型传统RRU Conducted and radiated requirement reference points 4.3.1 BS type 1-C&#xff08;传统RRU一般测试点就是连接天线的射频接头&#xff09; 4.3.2 BS type 1-H&#xff08;宏站MassiveMIMO 矩阵天线&#xff…

Nginx实现html页面注入浏览器监控js代码片段

一、背景 最近看到关于浏览器监控相关的东西&#xff0c;顺带着就记录一下其实现的大致原理过程。 在我们没对web应用做浏览器监控的时候&#xff0c;我们其实无法感知到用户对我们应用页面的使用习惯、使用中是否遇到问题&#xff0c;例如白屏情况出现多少次、请求失败情况、j…

ROS第 12 课 Launch 启动文件的使用方法

文章目录 第 12 课 Launch 启动文件的使用方法1.本节前言2.Lanuch 文件基本语法2.2 参数设置2.3 重映射嵌套 3.实操练习 第 12 课 Launch 启动文件的使用方法 1.本节前言 我们在前面的教程里面通过命令行来尝试运行新的节点。但随着创建越来越复杂的机器人系统中&#xff0c;打…

nest 集成 redis

1.准备工作 安装redis npm install ioredis pnpm install --save nestjs-redis ioredis pnpm install --save nestjsplus/redis 这个命令nest g res redis创建redis需要用的 之后再appmoudlue加入 providers: [ AppService, { provide: REDIS_CLIENT, async useFactory(…

【Java】Maven的基本使用

Maven的基本使用 Maven常用命令 complie&#xff1a;编译clean&#xff1a;清理test&#xff1a;测试package&#xff1a;打包install&#xff1a;安装 mvn complie mvn clean mvn test mvn package mvn installMaven生命周期 IDEA配置Maven Maven坐标 什么是坐标&#xff1f;…

可视化 | 【echarts】中国地图热力图

文章目录 &#x1f4da;html和css&#x1f4da;js&#x1f407;整体框架&#x1f407;getGeoJson&#x1f407;echarts绘图⭐️整体框架⭐️option配置项 【echarts】渐变条形折线复合图【echarts】金字塔图 &#x1f4da;html和css html&#xff1a;整合<!DOCTYPE html&g…

Docker:容器的两种运行模式(Foreground、Detached)

Docker容器进程有两种运行模式&#xff0c;通俗理解如下&#xff1a; 后台模式就是在后台运行&#xff0c;不会让当前进程卡主&#xff0c;你可以做其他事情。 前台模式是在前台运行&#xff0c;会导致当前卡住&#xff0c;并输出日志至当前控制台。 Foreground 前台模式&…

5G_射频测试_发射机测量(四)

6.2 Base station output power 用于测量载波发射功率的大小&#xff0c;功率越大小区半径越大但是杂散也会越大 载波功率&#xff08;用频谱仪测&#xff09;天线口功率&#xff08;用功率计测&#xff09;载波功率是以RBW为单位的filter测量的积分功率不同带宽的多载波测试时…

CAP 角度下的 Redis 与 Zookeeper 锁架构比较

在分布式系统设计中&#xff0c;CAP理论提供了一个重要的框架&#xff0c;帮助我们理解在一致性、可用性和分区容忍性之间的权衡。在这篇博客中&#xff0c;我们将从CAP的角度出发&#xff0c;比较Redis与Zookeeper在锁架构上的异同。 Redis锁架构&#xff1a; 一致性&#x…

java垃圾回收GC过程

GC&#xff08;Gabage Collection&#xff09; 用于回收堆中的垃圾数据 清理方法 1.标记-清理 对数据标记&#xff0c;然后清理 缺点&#xff1a;容易产生内存碎片 2.标记-整理 对标记后的数据清理&#xff0c;剩下数据前移 缺点&#xff1a;每次清理后数据都要迁移&#xff0…

JAVA算法-查找

目录 基本查找*&#xff1a; 二分查找*&#xff1a; 数据单调递增&#xff1a; 数据单调递减&#xff1a; 总结规律&#xff1a; 插值查找*&#xff1a; 斐波那契查找&#xff08;了解原理&#xff09;&#xff1a;以后补 分块 查找*&#xff1a; 特殊 情况&#xff0…

docker部署

//创建一个文件夹 mkdir soft //进入soft文件夹 cd soft 安装必要的系统工具: yum install -y yum-utils device-mapper-persistent-data lvm2 配置阿里云Docker Yum源: yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.rep…