大数跨境
0
0

WinForm 中异步加载数据并使用进度条

WinForm 中异步加载数据并使用进度条 DotNet技术匠
2025-09-06
0
导读:WinForm中异步加载数据并使用进度条。

前言

在开发WinForm应用程序时,经常会遇到需要加载大量数据的场景,比如读取文件、查询数据库或调用远程接口。如果这些操作直接在主线程中执行,UI界面就会出现"假死"现象——窗口无法响应用户的点击、拖动等操作,甚至可能显示"未响应"的提示。这种体验对用户来说非常不友好,容易让人误以为程序崩溃。

为了解决这个问题,我们需要将耗时操作放到后台线程中执行,同时通过进度条向用户反馈当前的处理进度。这样既能保证界面的流畅响应,又能提升用户的操作信心。

本文将介绍如何使用 .NET 提供的 BackgroundWorker 组件,实现数据的异步加载与进度可视化。

效果图

BackgroundWorker 的核心作用

BackgroundWorker 是 .NET Framework 中一个专为 WinForm 和 WPF 设计的异步操作组件,位于 System.ComponentModel 命名空间下。

它最大的优势在于:

  • 支持在后台线程执行耗时任务

  • 可以安全地向主线程报告进度

  • 支持取消操作

  • 能够捕获并转发异常

  • 实现了 IComponent 接口,可以直接从 Visual Studio 工具箱拖拽到窗体上使用

这使得它成为处理 WinForm 中异步任务的首选工具之一,尤其适合初学者快速上手多线程编程。

完整实现步骤与代码解析

下面我们通过一个具体的例子,展示如何使用 BackgroundWorker 实现异步加载数据并显示进度条。


1、界面设计

在 WinForm 窗体中添加以下控件:

  • 一个 ProgressBar(进度条)

  • 一个"开始"按钮(startButton

  • 一个"取消"按钮(cancelButton

  • 一个 TextBoxresultTextBox,用于显示日志)

  • 一个 BackgroundWorker 组件(命名为 bw

然后设置 BackgroundWorker 的两个关键属性:

WorkerReportsProgress:设为 True,启用进度报告功能

WorkerSupportsCancellation:设为 True,启用取消功能

2、DoWork 事件:执行后台任务

该事件在后台线程中运行,用于执行耗时操作。

注意:此处不能直接操作 UI 控件

private void bw_DoWork(object sender, DoWorkEventArgs e)
{
    var count = (int)e.Argument;
    for (int i = 1; i <= count; i++)
    {
        if (bw.CancellationPending)
        {
            e.Cancel = true;
            return;
        }
                    
        bw.ReportProgress(i);
        Thread.Sleep(200);      // 模拟耗时的任务
    }                          
}

关键点说明

e.Argument 可以接收 RunWorkerAsync() 传入的参数,在本例中是循环次数。

CancellationPending 用于检测用户是否点击了取消按钮。

ReportProgress(i) 用于向主线程报告当前进度,值为 i,将在 ProgressChanged 事件中接收。

3、ProgressChanged 事件:更新UI进度

该事件在主线程中执行,可以安全地操作 UI 控件。

private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    progressBar.Value = e.ProgressPercentage;
    resultTextBox.Text += DateTime.Now + "\r\n";
}

e.ProgressPercentage 即为 ReportProgress() 方法传入的值,用于更新进度条的当前值。

4、RunWorkerCompleted 事件:任务完成处理

无论任务成功、取消还是抛出异常,都会进入此事件,适合进行收尾工作和异常处理。

private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Cancelled)
        resultTextBox.Text += "任务取消。" + "\r\n";
    else if (e.Error != null)
        resultTextBox.Text += "出现异常: " + e.Error + "\r\n";
    else
        resultTextBox.Text += "任务完成。 " + "\r\n";
}

异常处理说明

如果 DoWork 中抛出异常,该异常不会直接中断程序,而是被封装到 e.Error 中,可以在本事件中捕获并提示用户。

5、启动与取消按钮的事件处理

private void startButton_Click(object sender, EventArgs e)
{
    progressBar.Value = 0;
    progressBar.Maximum = 10;

    resultTextBox.Text = "任务开始..." + "\r\n";
    bw.RunWorkerAsync(10);
}

点击"开始"按钮后,调用 RunWorkerAsync(10) 启动后台任务,并传入参数 10

private void cancelbutton_Click(object sender, EventArgs e)
{
    bw.CancelAsync();
}

点击"取消"按钮后,调用 CancelAsync() 发起取消请求。注意:这只是一个"请求",实际是否取消取决于 DoWork 中是否检查了 CancellationPending

6、完整代码示例

public partialclassForm1 : Form
{
    public Form1()
    {
        InitializeComponent();
        bw.DoWork += bw_DoWork;
        bw.ProgressChanged += bw_ProgressChanged;
        bw.RunWorkerCompleted += bw_RunWorkerCompleted;
    }

    private void startButton_Click(object sender, EventArgs e)
    {
        progressBar.Value = 0;
        progressBar.Maximum = 10;

        resultTextBox.Text = "任务开始..." + "\r\n";
        bw.RunWorkerAsync(10);
    }

    private void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        var count = (int)e.Argument;
        for (int i = 1; i <= count; i++)
        {
            if (bw.CancellationPending)
            {
                e.Cancel = true;
                return;
            }

            if (i == 2)
                thrownew Exception("出错啦!");
                    
            bw.ReportProgress(i);
            Thread.Sleep(200);      
        }                          
    }

    private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Cancelled)
            resultTextBox.Text += "任务取消。" + "\r\n";
        elseif (e.Error != null)
            resultTextBox.Text += "出现异常: " + e.Error + "\r\n";
        else
            resultTextBox.Text += "任务完成。 " + "\r\n";
    }

    private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        progressBar.Value = e.ProgressPercentage;
        resultTextBox.Text += DateTime.Now + "\r\n";
    }

    private void cancelbutton_Click(object sender, EventArgs e)
    {
        bw.CancelAsync();
    }
}

总结

通过 BackgroundWorker,我们能够轻松实现 WinForm 中的异步数据加载与进度反馈。

整个过程分为三个核心事件:

1、DoWork:在后台线程执行耗时任务,不能操作UI。

2、ProgressChanged:接收进度更新,可安全操作UI控件。

3、RunWorkerCompleted:处理任务完成、取消或异常情况。

这种方式不仅解决了界面假死的问题,还通过进度条提升了用户体验。虽然在现代开发中,async/await 已成为主流,但 BackgroundWorker 由于其简单直观的事件模型,仍然是 WinForm 项目中处理异步任务的可靠选择,尤其适合中小型项目或快速原型开发。

另外,BackgroundWorker 的异常转发机制也大大简化了错误处理逻辑,避免了跨线程异常导致程序崩溃的风险。

关键词

#WinForm#BackgroundWorker#异步加载#进度条#UI响应#DoWork#ProgressChanged#RunWorkerCompleted#CancellationPending#ReportProgress

最后
如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。也可以加入微信公众号[DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!

作者:firslien

出处:cnblogs.com/samgk/p/4774977.html
声明:网络内容,仅供学习,尊重版权,侵权速删,歉意致谢!



END



方便大家交流、资源共享和共同成长
纯技术交流群,需要加入的小伙伴请扫码,并备注加群



推荐阅读






WinForm 框架下的工控领域视觉检测
WPF 电表数据采集系统开发:CommunityToolkit.Mvvm 与 Prism 架构对比实践
基于 .NET 8 + React 的轻量高效库存管理系统(前后端分离)
WPF 实时工业监控大屏:ModBus协议集成与无边框动态可视化方案
C#/.NET 八月技术盘点:WPF/WinForm、机器视觉与工业上位机实践
图形化操作 Windows 服务?这个开源小工具做到了
.NET 9.0 一个可复用 WPF 界面框架
手把手教会设计 WinForm 高DPI兼容程序,告别字体模糊与控件乱飞

WPF + MVVM 自助式检验报告打印机的多框架实现

为什么 .NET 内存占用非常大?

从零搭建企业级 WinForm 框架:集成 SunnyUI控件 与 SqlSugar ORM
C# 部署 Yolov8 全攻略:OpenVINO 与 TensorRT  双引擎加速
WPF 一款通用的嵌入式测控上位机(灵活配置免重复)
C# 有什么惊艳到你的地方?
Avalonia UI 和 Electron 哪个性能高?
C# + Halcon 的模块化工业视觉通用图像处理工具(实用、高效、全场景覆盖)
开源工业级 WPF 数据大屏:基于 MVVM+ HandyControl 的实战项目
C# 的未来是 Avalonia 吗?
C# 开发桌面应用,如何做出漂亮的界面?
免费开源!基于 WPF + Scrcpy 的简洁易用 Android 投屏工具
手写 WinForm 图表控件:无依赖,支持曲线、饼图、点图和对象折线图等
企业级桌面架构如何选,MFC、WinForm 还是 WPF?一文说清
WinForm 控件自动缩放算法:简单实现自适应窗口大小
WPF 和 WinForm:.NET平台上的未来之战,谁能胜出?(投票)
干货推荐:五款功能强大的 .NET 开源工作流系统,拿来即用
全栈 .NET 低代码引擎:权限、工作流、API动态生成,开源即用
一款基于 .NET 的轻量级 ERP 进销存系统:扫码入库、订单变标签,直达发货
.NET 8 + Vue 3 的智能工厂 MES 快速开发框架:设备监控、数据大屏全覆盖
C# + OpenCvSharp 实现低成本开源单目结构光三维扫描
.NET 9 + React 基于 DDD架构的动态路由 + RBAC权限实战
基于 SunnyUI 的企业级 WinForm 快速开发框架,开箱即用!
免硬件方案!基于.NET 的摄像头扫码工具(支持回车/连续扫描)
工业级 MES 系统开发 WPF + MVVM 从入门到实战(全源码/收藏版)

C# 工业常用的控件库

C# 轻松搞定工业上位机程序开机自启

C# 工业视觉开发选择 Halcon 还是 OpenCV?

C# 上位机开发怎么学?给自动化工程师的建议

.NET 桌面应用 (WPF/WinForm) 高效自动更新解决方案

一行代码快速开发 AntdUI 风格的 WinForm 通用后台框架

WinForm + SQL Server + Modbus 实现仓库温控上位机系统开发

WinForm 开发的多功能工具:串口通信、加密解密、图像转换等功能

.NET 开源免费、功能强大的图表库 ScottPlot(WinForm/WPF 通用)

C#+ OpenCvSharp 工业视觉常用图像处理示例集(开箱即用,附源码)


觉得有收获?不妨分享让更多人受益

关注「DotNet技术匠」,共同提升技术实力


收藏
点赞
分享
在看

【声明】内容源于网络
0
0
DotNet技术匠
「DotNet技术匠」聚焦.NET核心,分享深度干货、实战技巧、最新资讯、优质资源,助你领跑技术赛道,赋能开发者成长。
内容 1715
粉丝 0
DotNet技术匠 「DotNet技术匠」聚焦.NET核心,分享深度干货、实战技巧、最新资讯、优质资源,助你领跑技术赛道,赋能开发者成长。
总阅读98
粉丝0
内容1.7k