首頁 後端開發 C#.Net教程 從0自學C#02--子線程訪問主線程(UI線程)控件

從0自學C#02--子線程訪問主線程(UI線程)控件

Feb 04, 2017 am 10:33 AM

如果使用多執行緒處理來提高 Windows 窗體應用程式的效能,則你必須確保以執行緒安全的方式呼叫控制項。

存取 Windows 窗體控制項不是本身就執行緒安全的。如果有兩個或兩個以上執行緒操作控制項的狀態,則可能迫使該控制項處於不一致狀態。可能出現其他與執行緒相關的 bug,例如爭用條件和死鎖。請務必確保以線程安全的方式存取控制項。

1.初學者常常遇到的問題

從未使用 Invoke 方法創建控制項的執行緒呼叫控制項是不安全的。下面是一個非線程安全的呼叫範例。執行時間會引發 InvalidOperationException 訊息,報錯「從並未建立該控制項的執行緒存取該控制項 控制項名稱」。

// This event handler creates a thread that calls a // Windows Forms control in an unsafe way.private void setTextUnsafeBtn_Click(    object sender, 
    EventArgs e)
{    this.demoThread = 
        new Thread(new ThreadStart(this.ThreadProcUnsafe));    this.demoThread.Start();
}// This method is executed on the worker thread and makes// an unsafe call on the TextBox control.private void ThreadProcUnsafe()
{    this.textBox1.Text = "This text was set unsafely.";
}
登入後複製


2.解決方法

如需對 Windows 窗體控制進行執行緒安全的呼叫。

①查詢控制項的 InvokeRequired 屬性。

②若 InvokeRequired 傳回 true,則用實際呼叫控制項的委託來呼叫 Invoke。

③若 InvokeRequired 傳回 false,則請直接呼叫控制項。

這裡分同步執行委託和非同步執行委託。

從0自學C#02--子線程訪問主線程(UI線程)控件

在以下程式碼範例中,在 ThreadProcSafe 方法中實作了執行緒安全的調用,該方法由後台執行緒執行。若 TextBox 控制項的 InvokeRequired 傳回 true,則 ThreadProcSafe 方法建立一個 SetTextCallback 實例並將其傳遞到窗體的 Invoke 方法。這導致在創建了 SetText 控制項的執行緒上呼叫 TextBox 方法,並且在該執行緒上下文中直接設定 Text 屬性。

// This event handler creates a thread that calls a 
// Windows Forms control in a thread-safe way.
private void setTextSafeBtn_Click(    
object sender, 
    EventArgs e)
{    this.demoThread = 
        new Thread(new ThreadStart(this.ThreadProcSafe));    
this.demoThread.Start();
}// This method is executed on the worker thread and makes
// a thread-safe call on the TextBox control.
private void ThreadProcSafe()
{    this.SetText("This text was set safely.");
}// This delegate enables asynchronous calls for setting
// the text property on a TextBox control.delegate void SetTextCallback(string text); 
// This method demonstrates a pattern for making thread-safe
// calls on a Windows Forms control. 
//
// If the calling thread is different from the thread that
// created the TextBox control, this method creates a
// SetTextCallback and calls itself asynchronously using the// Invoke method.
//
// If the calling thread is the same as the thread that created
// the TextBox control, the Text property is set directly. private void SetText(string text)
{    // InvokeRequired required compares the thread ID of the
    // calling thread to the thread ID of the creating thread.
    // If these threads are different, it returns true.
    //this.textBox1.InvokeRequired will be replaced by
    //this.InvokeRequired, if want to set many controls' 
    //attribute or text.
    if (this.textBox1.InvokeRequired)// or this.InvokeRequired
    {   
        SetTextCallback d = new SetTextCallback(SetText);        
this.Invoke(d, new object[] { text });
    }    else
    {        this.textBox1.Text = text;
    }
}
登入後複製

3.BackgroundWorker元件

在應用程式中實作多執行緒的首選方式是使用 BackgroundWorker 元件。 BackgroundWorker 元件為多執行緒處理使用事件驅動模型。後台執行緒運行你的 DoWork 事件處理程序,創建了你的控制項的執行緒運行 ProgressChanged 和 RunWorkerCompleted 事件處理程序。你可以從 ProgressChanged 和 RunWorkerCompleted 事件處理器中呼叫控制項。

①創建一種方法來進行你想在後台執行緒中進行的工作。不要呼叫由此方法中的主執行緒所建立的控制項。

②建立一種方法來報告後台工作結束後的後台工作結果。 在此方法中可以呼叫主執行緒所建立的控制項。

③將步驟 1 中建立的方法綁定到 DoWork 實例中的 BackgroundWorker 事件,並將步驟 2 中建立的方法綁定到相同實例的 RunWorkerCompleted 事件。

④若要啟動後台線程,請呼叫 RunWorkerAsync 實例的 BackgroundWorker 方法。

在以下程式碼範例中,DoWork 事件處理程序使用 Sleep 來模擬需要花費一些時間的工作。它不會呼叫該窗體的 TextBox 控制項。 TextBox 控制項的 Text 屬性直接在 RunWorkerCompleted 事件處理程序中設定。

// This BackgroundWorker is used to demonstrate the 
// preferred way of performing asynchronous operations.private BackgroundWorker backgroundWorker1; 
// This event handler starts the form's // BackgroundWorker by calling RunWorkerAsync.
//
// The Text property of the TextBox control is set
// when the BackgroundWorker raises the RunWorkerCompleted
// event.private void setTextBackgroundWorkerBtn_Click(    
object sender, 
    EventArgs e)
{    this.backgroundWorker1.RunWorkerAsync();
}// This event handler sets the Text property of the TextBox
// control. It is called on the thread that created the 
// TextBox control, so the call is thread-safe.
//
// BackgroundWorker is the preferred way to perform asynchronous
// operations.private void backgroundWorker1_RunWorkerCompleted(    
object sender, 
    RunWorkerCompletedEventArgs e)
{    this.textBox1.Text = 
        "This text was set safely by BackgroundWorker.";
}
登入後複製

也可透過使用 ProgressChanged 事件來報告後台任務的進度。如需包含該事件的範例,請參閱 BackgroundWorker。

以上就是 從0自學C#02--子執行緒存取主執行緒(UI執行緒)控制項的內容,更多相關內容請關注PHP中文網(www.php.cn)!


本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

使用 C# 的活動目錄 使用 C# 的活動目錄 Sep 03, 2024 pm 03:33 PM

使用 C# 的 Active Directory 指南。在這裡,我們討論 Active Directory 在 C# 中的介紹和工作原理以及語法和範例。

C# 序列化 C# 序列化 Sep 03, 2024 pm 03:30 PM

C# 序列化指南。這裡我們分別討論C#序列化物件的介紹、步驟、工作原理和範例。

C# 中的隨機數產生器 C# 中的隨機數產生器 Sep 03, 2024 pm 03:34 PM

C# 隨機數產生器指南。在這裡,我們討論隨機數產生器的工作原理、偽隨機數和安全數的概念。

C# 資料網格視圖 C# 資料網格視圖 Sep 03, 2024 pm 03:32 PM

C# 資料網格視圖指南。在這裡,我們討論如何從 SQL 資料庫或 Excel 檔案載入和匯出資料網格視圖的範例。

C# 中的階乘 C# 中的階乘 Sep 03, 2024 pm 03:34 PM

C# 階乘指南。這裡我們討論 C# 中階乘的介紹以及不同的範例和程式碼實作。

C# 中的模式 C# 中的模式 Sep 03, 2024 pm 03:33 PM

C# 模式指南。在這裡,我們討論 C# 中模式的介紹和前 3 種類型,以及其範例和程式碼實作。

c#多線程和異步的區別 c#多線程和異步的區別 Apr 03, 2025 pm 02:57 PM

多線程和異步的區別在於,多線程同時執行多個線程,而異步在不阻塞當前線程的情況下執行操作。多線程用於計算密集型任務,而異步用於用戶交互操作。多線程的優勢是提高計算性能,異步的優勢是不阻塞 UI 線程。選擇多線程還是異步取決於任務性質:計算密集型任務使用多線程,與外部資源交互且需要保持 UI 響應的任務使用異步。

C# 中的質數 C# 中的質數 Sep 03, 2024 pm 03:35 PM

C# 質數指南。這裡我們討論c#中素數的介紹和範例以及程式碼實作。

See all articles