精品秘无码一区二区三区老师-精品秘一区二三区免费雷安-精品蜜桃秘一区二区三区-精品蜜桃秘一区二区三区粉嫩-精品蜜桃一区二区三区-精品蜜臀国产aⅴ一区二区三区

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

WinForm 中解決 UI 假死問題的方法

admin
2024年12月27日 22:53 本文熱度 515

前言

WinForm中的UI假死其實是個老生常談的問題了,但最近還是很多人問我該如何解決,所以今天就來說明一下如何解決UI假死的問題。

實驗程序界面如下圖所示:

正文

方法一 async + await + Task

首先看下面一段代碼:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        // 開始
        private void btnStart_Click(object sender, EventArgs e)
        {
            string message = GetMessage();
            MessageBox.Show(message);
        }

        // 一個耗時任務(wù)
        private string GetMessage()
        {
            Thread.Sleep(10000);
            return "Hello World";
        }
    }
}

在上面的代碼中,GetMessage()方法耗時10秒鐘,如果你點擊按鈕,那么在10秒鐘內(nèi)窗體將處于假死狀態(tài)。

這種情況很常見,之所以會造成UI假死的原因也很簡單:某個函數(shù)耗時太久。

在遇見這種情況的時候,我們就可以考慮使用async + await + Task來解決,代碼如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        // 開始
        private async void btnStart_Click(object sender, EventArgs e)
        {
            string message = await GetMessage();
            MessageBox.Show(message);
        }

        // 一個耗時任務(wù)
        private async Task<stringGetMessage()
        {
            return await Task<string>.Run(() =>
            {
                Thread.Sleep(10000);
                return "Hello World";
            });
        }
    }
}

運行之后點擊按鈕,你會發(fā)現(xiàn)UI沒有假死,窗體可以隨意拖動了。

方法二:使用BackgroundWorker組件

在很多時候,我們需要動態(tài)顯示當(dāng)前的程序執(zhí)行進度,以便讓用戶了解程序已經(jīng)執(zhí)行到哪一步了。

很多同志都會這么寫:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        // 開始
        private void btnStart_Click(object sender, EventArgs e)
        {
            int max = pgbStatus.Maximum;
            for (int i = 1; i <= max; i++)
            {
                pgbStatus.Value++;
                Thread.Sleep(1000);
            }
        }
    }
}

功能確實是實現(xiàn)了,進度條能夠顯示當(dāng)前執(zhí)行的進度,可惜UI還是處于假死狀態(tài),所以用戶體驗還是不好。

其實WinForm已經(jīng)給我們提供了一個處理多線程任務(wù)的組件BackgroundWorker,使用它可以輕松讓你的程序告別UI假死,如下圖所示:

代碼如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            this.bgw.WorkerReportsProgress = true;
            this.bgw.WorkerSupportsCancellation = true;
            this.bgw.DoWork += DoWork;
            this.bgw.ProgressChanged += ProgressChanged;
            this.bgw.RunWorkerCompleted += RunWorkerCompleted;
        }

        // 開始
        private void btnStart_Click(object sender, EventArgs e)
        {
            if (bgw.IsBusy)
            {
                return;
            }
            bgw.RunWorkerAsync();
        }

        // DoWork
        private void DoWork(object sender, DoWorkEventArgs e)
        {
            int max = pgbStatus.Maximum;
            for (int i = 1; i <= max; i++)
            {
                bgw.ReportProgress(i);
                Thread.Sleep(1000);
            }
        }

        // ProgressChanged
        private void ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            pgbStatus.Value = e.ProgressPercentage;
        }

        // RunWorkerCompleted
        private void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            MessageBox.Show("完成");
        }
    }
}

運行程序點擊按鈕,你會發(fā)現(xiàn)UI沒有處于假死狀態(tài),窗體可以隨意拖動。
方法三:Task + 委托(回調(diào)函數(shù))
首先需要明確一點:UI線程位于主線程,如果想要在子線程里更新UI狀態(tài),必須要將其切換到主線程,最后進行更新操作。
UI控件一般會提供Invoke、InvokeRequired,其中InvokeRequired用于判斷是否有子線程在更新UI控件,如果有則返回true,Invoke用于將控制權(quán)切換到UI線程,代碼如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        // 開始
        private void btnStart_Click(object sender, EventArgs e)
        {
            Task task = Task.Run(() =>
            {
                int max = pgbStatus.Maximum;
                for (int i = 1; i <= max; i++)
                {
                    UpdateValue(i);
                    Thread.Sleep(1000);
                }
            });
        }

        // 處理線程
        private void UpdateValue(int num)
        {
            if (pgbStatus.InvokeRequired)
            {
                pgbStatus.Invoke(new Action<int>(UpdateValue), new object[] { num });
            }
            else
            {
                pgbStatus.Value = num;
            }
        }
    }
}

方法三也可以解決UI的假死問題,當(dāng)然也不一定要用Task,利用Thread也可以實現(xiàn)一樣的效果。
總結(jié)
通過上述方法,可以有效地解決 WinForms 應(yīng)用程序中 UI 假死的問題。選擇哪種方法取決于具體的場景和需求。BackgroundWorker 和 Task+ async/await 是最常用和推薦的方法,因為它們簡單易用且功能強大。ThreadPool和手動創(chuàng)建線程則適用于需要更高靈活性的場景。
無論選擇哪種方法,都要注意在更新 UI 時使用 Invoke或 BeginInvoke,以確保線程安全。
最后
如果你覺得這篇文章對你有幫助,不妨點個贊支持一下!你的支持是我繼續(xù)分享知識的動力。如果有任何疑問或需要進一步的幫助,歡迎隨時留言。也可以加入微信公眾號[DotNet技術(shù)匠] 社區(qū),與其他熱愛技術(shù)的同行一起交流心得,共同成長!

作者:碼農(nóng)家園

出處:codenong.com/cs106719464/
聲明:網(wǎng)絡(luò)內(nèi)容,僅供學(xué)習(xí),尊重版權(quán),侵權(quán)速刪,歉意致謝!


該文章在 2024/12/28 11:58:25 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點晴ERP是一款針對中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點晴PMS碼頭管理系統(tǒng)主要針對港口碼頭集裝箱與散貨日常運作、調(diào)度、堆場、車隊、財務(wù)費用、相關(guān)報表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點,圍繞調(diào)度、堆場作業(yè)而開發(fā)的。集技術(shù)的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點晴WMS倉儲管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務(wù)都免費,不限功能、不限時間、不限用戶的免費OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved

主站蜘蛛池模板: 丁香花chengren | 成人免费永久在线观看视频 | 日韩精品无码一区二区中文字幕 | 午夜精品一区二区三区av | 越南护士毛茸茸性 | 免费啪视频在线看视频 | 国产午夜免费视频片夜色 | 成人免费一区二区三区 | 国产精品久久久久久人妻精品A片 | 亚洲欧美动漫少妇自拍 | 日韩aⅴ在线高清免费看 | 一级做a爰全过程免费视频毛片 | 久久久精品456亚洲影院 | 人妻激情偷乱一区二区三区 | 最新国产毛片 | 99久久无码一区人妻A片蜜桃 | 精品欧美国产一区二区三区 | 午夜精品久久久久久久久久久久 | 一区精品视频在线观看免费 | 人妻内射一区二区在线视频 | 午夜人性色福利无码视频在 | 日韩免费夜色影院 | 国产欧美日韩一区二区三区在线 | 亚洲欧美综合网拍拍拍最新影院新 | 伊人久久大香线蕉av不变影院 | 国产色情A片国语露对白 | 亚洲精品成人AV在线观看爽翻 | 日日夜夜7799综合精品 | 精品卡一卡二乱码新区 | 日韩aⅴ精品一区二区三区 日韩aⅴ精品一区二区三 | 国产真实野战在线视频 | 日韩插啊免费视频在线观看 | 亚洲日本一线产区二线产区 | 亚洲av有码在线天堂 | 国精产品三区四区有限公司 | 激情国产一区二区三区四区 | 偷拍福利一区二区每日更新 | 亚洲日韩国产人成在线发布 | 一本久久久久免费精品不卡 | 亚洲国色天香卡2卡3卡4 | 日韩内射美女片在线 |