C# WPF中的GUI多线程技巧详解

news/2024/10/9 9:15:10/

1. 使用BackgroundWorker组件

代码示例:

 
public partial class MainWindow : Window
{private BackgroundWorker backgroundWorker = new BackgroundWorker();public MainWindow(){InitializeComponent();backgroundWorker.DoWork += BackgroundWorker_DoWork;backgroundWorker.RunWorkerCompleted += BackgroundWorker_RunWorkerCompleted;backgroundWorker.WorkerReportsProgress = true;backgroundWorker.WorkerSupportsCancellation = true;}private void StartButton_Click(object sender, RoutedEventArgs e){backgroundWorker.RunWorkerAsync();}private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e){// 长时间运行的任务for (int i = 0; i < 100; i++){if (backgroundWorker.CancellationPending){e.Cancel = true;return;}backgroundWorker.ReportProgress(i + 1);Thread.Sleep(100);}}private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e){if (e.Cancelled){MessageBox.Show("Task was canceled.");}else if (e.Error != null){MessageBox.Show("Error: " + e.Error.Message);}else{MessageBox.Show("Task completed.");}}
}

优点:

  • 提供了简单的方式来异步执行操作。

  • 支持进度更新和取消操作。

缺点:

  • 编程模型较为古老,不是基于任务并行库(TPL)。

使用场景:

  • 当需要简单的异步操作且不需要复杂的任务调度时。

2. 使用Task并行库(TPL)

代码示例:

 
public partial class MainWindow : Window
{public MainWindow(){InitializeComponent();}private async void StartButton_Click(object sender, RoutedEventArgs e){await Task.Run(() =>{// 长时间运行的任务for (int i = 0; i < 100; i++){Application.Current.Dispatcher.Invoke(() =>{// 更新UIProgressTextBlock.Text = $"Progress: {i + 1}";});Thread.Sleep(100);}});ProgressTextBlock.Text = "Task completed.";}
}

优点:

  • 基于.NET的Task并行库,是现代异步编程的标准。

  • 支持任务取消、继续与异常处理。

缺点:

  • 需要正确处理UI线程和后台线程之间的上下文切换。

使用场景:

  • 当需要进行复杂的异步编程和任务调度时。

3. 使用Dispatcher进行线程间通信

代码示例:

 
public partial class MainWindow : Window
{public MainWindow(){InitializeComponent();}private void StartButton_Click(object sender, RoutedEventArgs e){Thread backgroundThread = new Thread(DoWork);backgroundThread.Start();}private void DoWork(){for (int i = 0; i < 100; i++){Application.Current.Dispatcher.Invoke(() =>{// 更新UIProgressTextBlock.Text = $"Progress: {i + 1}";});Thread.Sleep(100);}Application.Current.Dispatcher.Invoke(() =>{ProgressTextBlock.Text = "Task completed.";});}
}

优点:

  • 允许直接控制线程的创建和管理。

  • 可以精确控制UI更新。

缺点:

  • 需要手动管理线程生命周期,增加了复杂性。

使用场景:

  • 当需要直接控制后台线程的行为时。

4. 使用数据绑定和INotifyPropertyChanged接口

代码示例:

 
public class ViewModel : INotifyPropertyChanged
{private string _progress;public string Progress{get { return _progress; }set{if (_progress != value){_progress = value;OnPropertyChanged(nameof(Progress));}}}public event PropertyChangedEventHandler PropertyChanged;protected virtual void OnPropertyChanged(string propertyName){PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));}public void DoWork(){// 长时间运行的任务for (int i = 0; i < 100; i++){Thread.Sleep(100);Progress = $"Progress: {i + 1}";}}
}

优点:

  • 通过数据绑定自动更新UI,减少了代码量。

  • 遵循MVVM设计模式,提高了代码的可维护性。

缺点:

  • 需要实现INotifyPropertyChanged接口,增加了实现的复杂性。

使用场景:

  • 当应用程序遵循MVVM设计模式时。

5. 使用Async/Await模式

代码示例:

 
public partial class MainWindow : Window
{public MainWindow(){InitializeComponent();}private async void StartButton_Click(object sender, RoutedEventArgs e){await DoWorkAsync();}private async Task DoWorkAsync(){for (int i = 0; i < 100; i++){await Task.Delay(100);ProgressTextBlock.Text = $"Progress: {i + 1}";}ProgressTextBlock.Text = "Task completed.";}
}

优点:

  • 代码简洁,易于理解和维护。

  • 自动处理线程间上下文切换。

缺点:

  • 不适用于所有类型的长时间运行任务。

使用场景:

  • 当需要在WPF应用程序中执行异步操作时。

总结

在C# WPF应用程序中,合理使用多线程技术可以显著提高应用程序的性能和用户体验。BackgroundWorker组件提供了一种简单的方式来执行后台操作;Task并行库(TPL)是现代异步编程的标准;Dispatcher是WPF中进行线程间通信的关键;数据绑定和INotifyPropertyChanged接口可以自动更新UI;Async/Await模式使得异步编程更加简单。开发者应根据具体的应用需求和场景,选择最合适的多线程实现方式。

往期精品推荐:

在国内默默无闻的.NET,在国外火的超乎想象?

C#的膨胀之路:创新还是灭亡

介绍.NET 6款好看的winform开源UI库

介绍一款最受欢迎的.NET 开源UI库

WPF第三方开源UI框架:打造独特体验的魔法师

WPF与Winform,你的选择是?

WinForm的前世今生

.NET成年了,然后呢?——编程界的逆袭传奇


http://www.ppmy.cn/news/1536570.html

相关文章

目标检测YOLO实战应用案例100讲-【目标检测】YOLOV11

目录 前言 算法原理 YOLO发展历程 什么是 YOLO11 YOLOv11 的主要特点 YOLO各版本概览 核心优势: YOLOv11改进方向 YOLOv11功能介绍 YOLOv11关键创新 YOLOv11 指标展示 YOLOV11实验 环境设置 准备数据集 训练模型 验证模型 应用领域 一、智慧交通与自动驾…

角色动画——RootMotion全解

1. Unity(2022)的应用 由Animtor组件控制 在Animation Clip下可进行详细设置 ​ 官方文档的介绍(Animation选项卡 - Unity 手册) 上述动画类型在Rag选项卡中设置: Rig 选项卡上的设置定义了 Unity 如何将变形体映射到导入模型中的网格&#xff0c;以便能够将其动画化。 对于人…

数学分析难点精解【1】

文章目录 有理数和无理数的问题有理数和无理数的区别与联系区别联系例题1&#xff1a;识别有理数和无理数例题2&#xff1a;有理数和无理数的运算例题3&#xff1a;有理数和无理数的应用 有理数和无理数的计算有理数的计算公式无理数的计算公式注意事项 根号运算规则1. 定义与性…

Vue的基本用法及模板语法

Vue.js使用了基于 HTML 的模板语法&#xff0c;允许开发者声明式地将 DOM 绑定至底层 Vue实例的数据。所有 Vue.js的模板都是合法的 HTML&#xff0c;所以能被遵循规范的浏览器和 HTML 解析器解析。 在底层的实现上&#xff0c;Vue将模板编译成虚拟 DOM 渲染函数。结合响应系…

【物流配送中心选址问题】基于退火算法混合粒子群算法

课题名称&#xff1a; 基于退火算法混合粒子群算法的物流配送中心选址问题 改进方向&#xff1a;模拟退火算法优化粒子群算法 代码获取方式&#xff08;付费&#xff09;&#xff1a; 模型说明&#xff1a; 待补充 Matlab仿真结果&#xff1a; 1. 模型优化后的仿真结果 2…

文章被modelscope转载

笔者的这篇文章《vllm部署Mistral-Large-Instruct-2407》被转载到modelscope了&#xff0c;记录一下&#xff1a; 原文&#xff1a;https://blog.csdn.net/ybdesire/article/details/140691972转载&#xff1a;https://community.modelscope.cn/66a30e05962e585a2567675b.html

优秀博客:小程序通信方法在 Vue 3 中的对应技术

小程序通信方法在 Vue 3 中的对应技术 在当今的前端开发中&#xff0c;不同框架之间的通信方法往往有着异曲同工之妙。本文将探讨小程序中的通信方法&#xff0c;并揭示它们在 Vue 3 中的对应技术。通过对比&#xff0c;我们可以更好地理解这些概念在不同框架中的实现与应用。…

SQL进阶技巧:如何计算累计指标?

目录 0 需求描述 1 数据准备 2 问题分析 3 小结 如果觉得本文对你有帮助&#xff0c;想进一步学习SQL语言这门艺术的&#xff0c;那么不妨也可以选择去看看我的博客专栏 &#xff0c;部分内容如下&#xff1a; 数字化建设通关指南 专栏 原价99&#xff0c;现在活动价59.…