【C#】Thread.Join()、異步等待和直接join

JogThread.Join() 是 .NET 中 System.Threading.Thread 類的一個方法,用來讓當前調用線程暫停執行,直到目標線程(這里是 JogThread)終止為止。以下是它的核心語義和你在 UI 代碼里需要注意的幾個相關知識點。


1. Thread.Join() 的作用

  • 阻塞調用線程:當你在 A 線程上調用 someThread.Join(),A 線程會停在這一行,直到 someThread 運行完畢(自然退出或拋異常結束)。
  • 無返回值:標準的 Join() 會一直等,沒有超時;也有重載 Join(int millisecondsTimeout),可以設置最長等待時間。
// workerThread 是另一個正在執行的線程
workerThread.Start();
// … 做點別的 …
workerThread.Join();  
// 只有當 workerThread 完全結束后,下面這一行才會執行
Console.WriteLine("workerThread 已退出");

2. IsAliveJoin 常見組合

if (JogThread != null && JogThread.IsAlive)
{JogThread.Join();
}
  • IsAlive 檢查線程還存活(沒終止)再調用 Join
  • 否則如果 Join 在已經結束的線程上調用,.NET 會立刻返回,不會拋異常。

3. winform中在 UI 線程上調用 Join 會帶來什么?

  • UI 凍結:WinForms/WPF 的 UI 線程負責不停地處理消息隊列(鼠標點擊、重繪、動畫等)。一旦你在 UI 線程上執行 .Join(),它就不再處理消息,界面完全卡住,直到子線程終結。
  • 無法交互:用戶點擊按鈕、拖動窗口都沒有反應,甚至操作系統會提示“應用無響應”。

4. 界面卡在了 Join 那里的原因?

  • 若是按鈕事件處理器本身就在 UI 線程上。
  • 當用戶點擊“xxxx’”觸發邏輯時,如果代碼進入了 if (JogThread.IsAlive) JogThread.Join();,UI 線程就停在那里等后臺 JogThread 結束。
  • JogThread 可能又在等待 UI 線程釋放某個資源或控件,結果雙向等待 —— 死鎖

5. 如何避免 UI 線程被 Join 阻塞?

5.1 用異步等待而不是直接 Join

把阻塞 Join 的工作扔到后臺去,再用 await 回到 UI 線程:

// 在 async 方法里
if (JogThread != null && JogThread.IsAlive)
{await Task.Run(() => JogThread.Join());
}

這樣,UI 線程發起 await 后會掛起這次事件但繼續處理消息。

5.2 完全移除 Join,改成事件/回調

  • 在后臺線程跑完后,觸發一個事件(如 JogFinished),讓 UI 在回調里恢復按鈕:
// 后臺線程結束時
JogFinished?.Invoke(this, EventArgs.Empty);// UI 訂閱該事件
jogService.JogFinished += (_,__)=>this.Invoke(() => { btnPos.Enabled = btnNeg.Enabled = true; });

這樣根本不需要在 UI 線程上等待。

5.3 用更現代的 Task 代替 Thread

  • 如果你把 RunJogThread_pJog 改為返回 Task 的異步方法,就可以直接 await 它,而不用操心 Join

    await jogService.RunJogAsync();
    // 到這兒就表示后臺跑完了
    

6. 其他

  • 線程安全:任何跨線程操作 UI 控件都必須用 Invoke/BeginInvoke 回到 UI 線程。
  • 超時等待Join(int timeout) 可以避免無限期掛起。
  • 取消機制:配合 CancellationToken,讓后臺線程在收到取消請求后優雅退出,不靠死等。
  • 后臺線程與前臺線程Thread.IsBackground 屬性決定程序退出時是否等待該線程結束。

異步等待而不是直接 Join

簡單來說,二者的核心區別在于:


1. 調用線程是否被 阻塞

  • 直接 Join()

    // 運行在 UI 線程里
    if (jogThread.IsAlive)jogThread.Join();  // ★ 這里 UI 線程被堵住,什么消息都收不到
    

    Join() 會立刻“把調用它的線程”停住,直到目標線程結束——UI 線程一停,就不會刷新界面、響應點擊或重繪。

  • 異步等待

    // async 方法里,仍在 UI 線程開始
    if (jogThread.IsAlive)await Task.Run(() => jogThread.Join());
    // ★ 這里 UI 線程會把控制權讓出去(繼續處理消息),等后臺完成后再回來
    

    Task.Run(() => Join()) 會把“等待 Join() 完成”這件事拿到線程池線程上去做,await 則讓當前(UI)方法“掛起”,釋放 UI 線程去做別的事,等后臺那塊兒真正完成后再把結果繼續推回 UI 線程。


2. UI 響應性

  • Join(): 長時間等待會讓界面“卡死”——看起來像“假死”或“無響應”。
  • await Task.Run(...): 等待期間 UI 線程依然可以處理鼠標、鍵盤、重繪等消息,保持流暢。

3. 異常與超時控制

  • Join(): 沒有超時,你只能堵著等;如果想超時要用 Join(timeout),還得寫判斷邏輯。
  • Task.Run(...); await: 可配合 CancellationTokenTask.WhenAny + Task.Delay 做超時、取消都更自然。

4. 代碼可維護性

  • 同步阻塞 風格的代碼嵌套過多會變得難讀。
  • 異步/await 風格能讓“先發起、然后等結果再繼續”寫得像直線流程,也更容易和現代異步 API(I/O、網絡、定時器)配合。

小對比表

Join()await Task.Run(() => Join())
調用線程同一線程(可能是 UI)把阻塞邏輯轉到線程池線程,UI 線程自由
UI 響應★ 卡死、假死? 保持流暢
超時/取消需要 Join(timeout) 或額外判斷可輕松配合 CancellationTokenTask.Delay
代碼直觀度同步嵌套易混亂異步/await 更自然,易讀

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/81083.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/81083.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/81083.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

牛客網NC22012:判斷閏年問題詳解

牛客網NC22012:判斷閏年問題詳解 📝 題目描述 題號:NC22012(牛客網) 時間限制:C/C/Rust/Pascal 1秒,其他語言2秒 空間限制:C/C/Rust/Pascal 32 M,其他語言64 M 判斷一個…

鴻蒙開發——1.ArkTS聲明式開發(UI范式基本語法)

鴻蒙開發——1、ArkTS聲明式開發:UI范式基本語法 [TOC](鴻蒙開發——1、ArkTS聲明式開發:UI范式基本語法)一、ArkTS的基本組成(1)核心概念(像貼標簽一樣控制組件)(2)基礎工具包(現成的積木塊&am…

【SPIN】PROMELA語言編程入門基礎語法(SPIN學習系列--1)

PROMELA(Protocol Meta Language)是一種用于描述和驗證并發系統的形式化建模語言,主要與SPIN(Simple Promela Interpreter)模型檢查器配合使用。本教程將基于JSPIN(SPIN的Java圖形化版本)&#…

Automatic Recovery of the Atmospheric Light in Hazy Images論文閱讀

Automatic Recovery of the Atmospheric Light in Hazy Images 1. 論文的研究目標與實際意義1.1 研究目標1.2 實際問題與產業意義2. 論文的創新方法、模型與公式2.1 方法框架2.1.1 方向估計(Orientation Estimation)2.1.2 幅值估計(Magnitude Estimation)2.2 與傳統方法的對…

基于微信小程序的在線聊天功能實現:WebSocket通信實戰

基于微信小程序的在線聊天功能實現:WebSocket通信實戰 摘要 本文將詳細介紹如何使用微信小程序結合WebSocket協議開發一個實時在線聊天功能。通過完整的代碼示例和分步解析,涵蓋界面布局、WebSocket連接管理、消息交互邏輯及服務端實現,適合…

速通:國際數字影像產業園園區服務體系

速通:國際數字影像產業園園區服務體系 國際數字影像產業園服務體系致力于構建全周期、多維度、高效率的產業賦能平臺,旨在優化營商環境,激發企業活力,推動數字影像產業集群化、高端化發展。 一、基礎運營與智慧管理服務 智慧化…

DeerFlow:字節新一代 DeepSearch 框架

項目地址:https://github.com/bytedance/deer-flow/ 【全新的 Multi-Agent 架構設計】獨家設計的 Research Team 機制,支持多輪對話、多輪決策和多輪任務執行。與 LangChain 原版 Supervisor 相比,顯著減少 Tokens 消耗和 API 調用次數&#…

MySQL 大表中添加索引的兩種常見方式及其優缺點分析

引言 在數據庫性能優化過程中,給大表添加索引是一項常見且重要的操作。由于大表數據量龐大,索引的創建過程往往涉及較高的系統開銷和復雜的操作流程。本文將介紹兩種在大表中添加索引的常見方法:直接添加索引和表復制方式,分別分…

Ubuntu系統掛載磁盤并配置開機自動掛載

今天買了個服務器然后掛載了一個500G的磁盤,但是登錄進去后發看不到,就是下面這樣的 只能看到100G的系統盤 rootecm-74de:/usr/local# df -h Filesystem Size Used Avail Use% Mounted on tmpfs 3.1G 1.1M 3.1G 1% /run /dev/vda2 …

Android開發-Application

在Android應用開發中,Application類扮演著非常重要的角色。它作為整個應用程序的全局單例實例存在,在應用啟動時最先被創建,并且在整個應用生命周期內持續存在。通過自定義Application類,開發者可以執行全局初始化操作、管理全局狀…

邊緣計算平臺

本文來源 : 騰訊元寶 邊緣計算平臺是一種在靠近數據源頭的網絡邊緣側部署的分布式計算架構,通過融合網絡、計算、存儲和應用核心能力,就近提供實時、低延遲的智能服務。以下是其核心要點: ??1. 定義與特點?? ??定義??&a…

Spring 框架 JDBC 模板技術詳解

一、JDBC 模板技術概述 在傳統 JDBC 開發中,開發人員需要手動處理數據庫連接(Connection)、事務管理、語句執行(Statement)和結果集(ResultSet)等繁瑣操作,不僅代碼冗余度高&#x…

Axure難點解決分享:統計分析頁面引入Echarts示例動態效果

親愛的小伙伴,在您瀏覽之前,煩請關注一下,在此深表感謝! Axure產品經理精品視頻課已登錄CSDN可點擊學習https://edu.csdn.net/course/detail/40420 課程主題:統計分析頁面引入Echarts示例動態效果 主要內容:echart示例引入、大小調整、數據導入 應用場景:統計分析頁面…

SpringBoot 數據校驗與表單處理:從入門到精通(萬字長文)

一、SpringBoot 數據驗證基礎 1.1 數據驗證的重要性 在現代Web應用開發中,數據驗證是保證系統安全性和數據完整性的第一道防線。沒有經過驗證的用戶輸入可能導致各種安全問題,如SQL注入、XSS攻擊,或者簡單的業務邏輯錯誤。 數據驗證的主要…

Ubuntu 22.04(WSL2)使用 Docker 安裝 Zipkin 和 Skywalking

Ubuntu 22.04(WSL2)使用 Docker 安裝 Zipkin 和 Skywalking 分布式追蹤工具在現代微服務架構中至關重要,它們幫助開發者監控請求在多個服務之間的流動,識別性能瓶頸和潛在錯誤。本文將指導您在 Ubuntu 22.04(WSL2 環境…

python打卡day25@浙大疏錦行

知識點回顧: 1.異常處理機制 2.debug過程中的各類報錯 3.try-except機制 4.try-except-else-finally機制 在即將進入深度學習專題學習前,我們最后差缺補漏,把一些常見且重要的知識點給他們補上,加深對代碼和流程的理解。 作業&a…

鴻蒙OSUniApp 開發實時聊天頁面的最佳實踐與實現#三方框架 #Uniapp

使用 UniApp 開發實時聊天頁面的最佳實踐與實現 在移動應用開發領域,實時聊天功能已經成為許多應用不可或缺的組成部分。本文將深入探討如何使用 UniApp 框架開發一個功能完善的實時聊天頁面,從布局設計到核心邏輯實現,帶領大家一步步打造專…

43、Server.UrlEncode、HttpUtility.UrlDecode的區別?

Server.UrlEncode 和 HttpUtility.UrlDecode 是 .NET 中用于處理 URL 編碼/解碼的兩個不同方法,主要區別在于所屬命名空間、使用場景和具體行為。以下是詳細對比: 1. 所屬類庫與命名空間 Server.UrlEncode 屬于 System.Web.HttpServerUtility 類。通常…

代碼隨想錄 算法訓練 Day1:數組

題目一: 給定一個 n 個元素有序的(升序)整型數組 nums 和一個目標值 target ,寫一個函數搜索 nums 中的 target,如果目標值存在返回下標,否則返回 -1。 示例 1: 輸入: nums [-1,0,3,5,9,12], target …

容器技術 20 年:顛覆、重構與重塑軟件世界的力量

目錄 容器技術發展史 虛擬化技術向容器技術轉變 Docker的橫空出世 容器編排技術與Kubernetes 微服務的出現與Istio 工業標準的容器運行時 容器技術與 DevOps 的深度融合? 無服務架構推波助瀾 展望未來發展方向 從 20 世紀硬件虛擬化的笨重,到操作系統虛擬…