實用指南:C#中優雅更新GUI的基礎和高級技巧(WinForms和WPF)

来源:https://www.cnblogs.com/hanbing81868164/p/18079548
-Advertisement-
Play Games

概述:以上內容詳細介紹了在C#中如何從另一個線程更新GUI,包括基礎功能和高級功能。對於WinForms,使用`Control.Invoke`;對於WPF,使用`Dispatcher.Invoke`。高級功能使用`SynchronizationContext`實現線程間通信,確保清晰、可讀性高的代碼 ...


 

概述:以上內容詳細介紹了在C#中如何從另一個線程更新GUI,包括基礎功能和高級功能。對於WinForms,使用`Control.Invoke`;對於WPF,使用`Dispatcher.Invoke`。高級功能使用`SynchronizationContext`實現線程間通信,確保清晰、可讀性高的代碼。

在C#中,從另一個線程更新GUI通常需要使用UI線程的同步上下文(SynchronizationContext)或者專門用於在UI線程執行操作的方法(Control.InvokeDispatcher.Invoke)。下麵分別給出在WinForms和WPF中的基礎功能和高級功能的實例源代碼。

在WinForms中更新GUI:

基礎功能:

  1. 創建WinForms應用程式: 創建一個包含按鈕和標簽的WinForms應用程式。
  2. 創建後臺線程: 使用Thread類或Task.Run創建一個後臺線程,模擬耗時操作。
  3. 使用Invoke更新UI: 在後臺線程中使用Control.Invoke更新UI。

示例源代碼:

using System;
using System.Threading;
using System.Windows.Forms;

namespace WinFormsThreadedGUIUpdate
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

        private void btnStartTask_Click(object sender, EventArgs e)
        {
            // 啟動後臺任務
            Thread thread = new Thread(PerformTask);
            thread.Start();
        }

        private void PerformTask()
        {
            // 模擬耗時操作
            Thread.Sleep(3000);

            // 在UI線程上更新標簽文本
            UpdateLabel("Task 完成!");
        }

        private void UpdateLabel(string text)
        {
            if (lblStatus.InvokeRequired)
            {
                // 在UI線程上非同步執行更新操作
                lblStatus.Invoke(new Action(() => lblStatus.Text = text));
            }
            else
            {
                // 在UI線程上直接更新操作
                lblStatus.Text = text;
            }
        }
    }
}

在WPF中更新GUI:

基礎功能:

  1. 創建WPF應用程式: 創建一個包含按鈕和標簽的WPF應用程式。
  2. 創建後臺線程: 使用Task.Run創建一個後臺線程,模擬耗時操作。
  3. 使用Dispatcher更新UI: 在後臺線程中使用Dispatcher.Invoke更新UI。

示例源代碼:

using System;
using System.Threading;
using System.Windows;

namespace WPFThreadedGUIUpdate
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void btnStartTask_Click(object sender, RoutedEventArgs e)
        {
            // 啟動後臺任務
            Task.Run(() =>
            {
                // 模擬耗時操作
                Thread.Sleep(3000);

                // 在UI線程上更新標簽文本
                UpdateLabel("Task 完成!");
            });
        }

        private void UpdateLabel(string text)
        {
            if (Dispatcher.CheckAccess())
            {
                // 在UI線程上直接更新操作
                lblStatus.Content = text;
            }
            else
            {
                // 在UI線程上非同步執行更新操作
                Dispatcher.Invoke(new Action(() => lblStatus.Content = text));
            }
        }
    }
}

高級功能:

在高級功能中,WinForms和WPF均可以使用SynchronizationContext進行線程間通信,代碼更為簡潔。

示例源代碼:

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AdvancedThreadedGUIUpdate
{
    public partial class MainForm : Form
    {
        private readonly SynchronizationContext synchronizationContext;

        public MainForm()
        {
            InitializeComponent();

            // 獲取當前同步上下文
            synchronizationContext = SynchronizationContext.Current;
        }

        private void btnStartTask_Click(object sender, EventArgs e)
        {
            // 啟動後臺任務
            Task.Run(() =>
            {
                // 模擬耗時操作
                Thread.Sleep(3000);

                // 在UI線程上更新標簽文本
                synchronizationContext.Post(new SendOrPostCallback(UpdateLabel), "Task 完成!");
            });
        }

        private void UpdateLabel(object state)
        {
            // 在UI線程上更新標簽文本
            lblStatus.Text = state.ToString();
        }
    }
}

在WPF中,Dispatcher本身就是一種同步上下文,所以代碼更為簡潔,無需額外的同步上下文對象。高級功能的WPF示例代碼與基礎功能示例代碼相似。

源代碼:https://pan.baidu.com/s/1BtKPnYujG5KO-poCnzKk7A?pwd=6666 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本文介紹基於R語言中的geodetector包,依據多張柵格圖像數據,實現地理探測器(Geodetector)操作的詳細方法~ ...
  • 在一次項目中,在給客戶做系統時,需要調用客戶的系統獲取數據,客戶提供了獲取Token和獲取數據的介面,用戶名和密碼,認證方式是基於Bearer的,通過學習和找資料,提供一個C#示例 一個C#示例 1、傳入語句獲取數據 /// <summary> /// 傳入語句獲取數據 /// </summary> ...
  • 在 CYQ.Data 版本更新的這麼多年,中間過程的版本都在完善各種功能。基於需要支持或相容的代碼越多,很多時候,常規思維,都把相關功能完成,就結束了。實現過程中,無法避免的會用到大量的反射、鎖等對性能有所影響的邏輯代碼。CYQ.Data 從V5.9 版本開始,開始大規模的優化調整代碼,目前穩定在 ... ...
  • 1.OleDb方式: 使用.NET Framework內置的System.Data.OleDb命名空間中的類,可以將Excel文件當作資料庫來讀取數據。這種方式適用於較舊版本的Excel文件(.xls格式,即Excel 2003及更早版本)。 using System.Data.OleDb; // ...
  • 一、引言 在.NET開發中,操作Office文檔(特別是Excel和Word)是一項常見的需求。然而,在伺服器端或無Microsoft Office環境的場景下,直接使用Office Interop可能會面臨挑戰。為瞭解決這個問題,開源庫NPOI應運而生,它提供了無需安裝Office即可創建、讀取和 ...
  • 一、引言 在現代應用程式開發中,尤其是在涉及I/O操作(如網路請求、文件讀寫等)時,非同步編程成為了提高性能和用戶體驗的關鍵技術。C#作為.NET框架下的主流開發語言,提供了強大的非同步編程支持,通過async/await關鍵字,可以讓開發者以同步的方式編寫非同步代碼,極大地簡化了非同步編程的複雜性。本文將 ...
  • 支持.Net/.Net Core/.Net Framework,可以部署在Docker, Windows, Linux, Mac。 常見的ORM技術(比如:Entity Framework,Dapper,SqlSugar,NHibernate,等…),它們不是在做Sql語句的程式化變種,就是在做Sq ...
  • Nuget包 Microsoft.Extensions.Telemetry.Abstractions 包含的新的日誌記錄source generator,它支持使用[LogProperties]將整個對象作為State與日誌一起記錄。 我將展示一種方法來控制如何使用[LogProperties]對象 ...
一周排行
    -Advertisement-
    Play Games
  • 基於.NET Framework 4.8 開發的深度學習模型部署測試平臺,提供了YOLO框架的主流系列模型,包括YOLOv8~v9,以及其系列下的Det、Seg、Pose、Obb、Cls等應用場景,同時支持圖像與視頻檢測。模型部署引擎使用的是OpenVINO™、TensorRT、ONNX runti... ...
  • 十年沉澱,重啟開發之路 十年前,我沉浸在開發的海洋中,每日與代碼為伍,與演算法共舞。那時的我,滿懷激情,對技術的追求近乎狂熱。然而,隨著歲月的流逝,生活的忙碌逐漸占據了我的大部分時間,讓我無暇顧及技術的沉澱與積累。 十年間,我經歷了職業生涯的起伏和變遷。從初出茅廬的菜鳥到逐漸嶄露頭角的開發者,我見證了 ...
  • C# 是一種簡單、現代、面向對象和類型安全的編程語言。.NET 是由 Microsoft 創建的開發平臺,平臺包含了語言規範、工具、運行,支持開發各種應用,如Web、移動、桌面等。.NET框架有多個實現,如.NET Framework、.NET Core(及後續的.NET 5+版本),以及社區版本M... ...
  • 前言 本文介紹瞭如何使用三菱提供的MX Component插件實現對三菱PLC軟元件數據的讀寫,記錄了使用電腦模擬,模擬PLC,直至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1. PLC開發編程環境GX Works2,GX Works2下載鏈接 https:// ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • 1、jQuery介紹 jQuery是什麼 jQuery是一個快速、簡潔的JavaScript框架,是繼Prototype之後又一個優秀的JavaScript代碼庫(或JavaScript框架)。jQuery設計的宗旨是“write Less,Do More”,即倡導寫更少的代碼,做更多的事情。它封裝 ...
  • 前言 之前的文章把js引擎(aardio封裝庫) 微軟開源的js引擎(ChakraCore))寫好了,這篇文章整點js代碼來測一下bug。測試網站:https://fanyi.youdao.com/index.html#/ 逆向思路 逆向思路可以看有道翻譯js逆向(MD5加密,AES加密)附完整源碼 ...
  • 引言 現代的操作系統(Windows,Linux,Mac OS)等都可以同時打開多個軟體(任務),這些軟體在我們的感知上是同時運行的,例如我們可以一邊瀏覽網頁,一邊聽音樂。而CPU執行代碼同一時間只能執行一條,但即使我們的電腦是單核CPU也可以同時運行多個任務,如下圖所示,這是因為我們的 CPU 的 ...
  • 掌握使用Python進行文本英文統計的基本方法,並瞭解如何進一步優化和擴展這些方法,以應對更複雜的文本分析任務。 ...
  • 背景 Redis多數據源常見的場景: 分區數據處理:當數據量增長時,單個Redis實例可能無法處理所有的數據。通過使用多個Redis數據源,可以將數據分區存儲在不同的實例中,使得數據處理更加高效。 多租戶應用程式:對於多租戶應用程式,每個租戶可以擁有自己的Redis數據源,以確保數據隔離和安全性。 ...