翼度科技»论坛 编程开发 .net 查看内容

实用指南:C#中优雅更新GUI的基础和高级技巧(WinForms和WPF)

6

主题

6

帖子

18

积分

新手上路

Rank: 1

积分
18
 
概述:以上内容详细介绍了在C#中如何从另一个线程更新GUI,包括基础功能和高级功能。对于WinForms,使用`Control.Invoke`;对于WPF,使用`Dispatcher.Invoke`。高级功能使用`SynchronizationContext`实现线程间通信,确保清晰、可读性高的代码。
在C#中,从另一个线程更新GUI通常需要使用UI线程的同步上下文(SynchronizationContext)或者专门用于在UI线程执行操作的方法(Control.Invoke或Dispatcher.Invoke)。下面分别给出在WinForms和WPF中的基础功能和高级功能的实例源代码。
在WinForms中更新GUI:

基础功能:


  • 创建WinForms应用程序: 创建一个包含按钮和标签的WinForms应用程序。
  • 创建后台线程: 使用Thread类或Task.Run创建一个后台线程,模拟耗时操作。
  • 使用Invoke更新UI: 在后台线程中使用Control.Invoke更新UI。
示例源代码:
  1. using System;
  2. using System.Threading;
  3. using System.Windows.Forms;
  4. namespace WinFormsThreadedGUIUpdate
  5. {
  6.     public partial class MainForm : Form
  7.     {
  8.         public MainForm()
  9.         {
  10.             InitializeComponent();
  11.         }
  12.         private void btnStartTask_Click(object sender, EventArgs e)
  13.         {
  14.             // 启动后台任务
  15.             Thread thread = new Thread(PerformTask);
  16.             thread.Start();
  17.         }
  18.         private void PerformTask()
  19.         {
  20.             // 模拟耗时操作
  21.             Thread.Sleep(3000);
  22.             // 在UI线程上更新标签文本
  23.             UpdateLabel("Task 完成!");
  24.         }
  25.         private void UpdateLabel(string text)
  26.         {
  27.             if (lblStatus.InvokeRequired)
  28.             {
  29.                 // 在UI线程上异步执行更新操作
  30.                 lblStatus.Invoke(new Action(() => lblStatus.Text = text));
  31.             }
  32.             else
  33.             {
  34.                 // 在UI线程上直接更新操作
  35.                 lblStatus.Text = text;
  36.             }
  37.         }
  38.     }
  39. }
复制代码
在WPF中更新GUI:

基础功能:


  • 创建WPF应用程序: 创建一个包含按钮和标签的WPF应用程序。
  • 创建后台线程: 使用Task.Run创建一个后台线程,模拟耗时操作。
  • 使用Dispatcher更新UI: 在后台线程中使用Dispatcher.Invoke更新UI。
示例源代码:
  1. using System;
  2. using System.Threading;
  3. using System.Windows;
  4. namespace WPFThreadedGUIUpdate
  5. {
  6.     public partial class MainWindow : Window
  7.     {
  8.         public MainWindow()
  9.         {
  10.             InitializeComponent();
  11.         }
  12.         private void btnStartTask_Click(object sender, RoutedEventArgs e)
  13.         {
  14.             // 启动后台任务
  15.             Task.Run(() =>
  16.             {
  17.                 // 模拟耗时操作
  18.                 Thread.Sleep(3000);
  19.                 // 在UI线程上更新标签文本
  20.                 UpdateLabel("Task 完成!");
  21.             });
  22.         }
  23.         private void UpdateLabel(string text)
  24.         {
  25.             if (Dispatcher.CheckAccess())
  26.             {
  27.                 // 在UI线程上直接更新操作
  28.                 lblStatus.Content = text;
  29.             }
  30.             else
  31.             {
  32.                 // 在UI线程上异步执行更新操作
  33.                 Dispatcher.Invoke(new Action(() => lblStatus.Content = text));
  34.             }
  35.         }
  36.     }
  37. }
复制代码
高级功能:

在高级功能中,WinForms和WPF均可以使用SynchronizationContext进行线程间通信,代码更为简洁。
示例源代码:
  1. using System;
  2. using System.Threading;
  3. using System.Threading.Tasks;
  4. using System.Windows.Forms;
  5. namespace AdvancedThreadedGUIUpdate
  6. {
  7.     public partial class MainForm : Form
  8.     {
  9.         private readonly SynchronizationContext synchronizationContext;
  10.         public MainForm()
  11.         {
  12.             InitializeComponent();
  13.             // 获取当前同步上下文
  14.             synchronizationContext = SynchronizationContext.Current;
  15.         }
  16.         private void btnStartTask_Click(object sender, EventArgs e)
  17.         {
  18.             // 启动后台任务
  19.             Task.Run(() =>
  20.             {
  21.                 // 模拟耗时操作
  22.                 Thread.Sleep(3000);
  23.                 // 在UI线程上更新标签文本
  24.                 synchronizationContext.Post(new SendOrPostCallback(UpdateLabel), "Task 完成!");
  25.             });
  26.         }
  27.         private void UpdateLabel(object state)
  28.         {
  29.             // 在UI线程上更新标签文本
  30.             lblStatus.Text = state.ToString();
  31.         }
  32.     }
  33. }
复制代码
在WPF中,Dispatcher本身就是一种同步上下文,所以代码更为简洁,无需额外的同步上下文对象。高级功能的WPF示例代码与基础功能示例代码相似。
源代码:https://pan.baidu.com/s/1BtKPnYujG5KO-poCnzKk7A?pwd=6666 
 



来源:https://www.cnblogs.com/hanbing81868164/p/18079548
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具