首頁  >  文章  >  後端開發  >  C# WinForm多執行緒開發(一) Thread類別庫

C# WinForm多執行緒開發(一) Thread類別庫

黄舟
黄舟原創
2017-02-20 10:56:321835瀏覽

原文位址:點選開啟連結

[摘要]本文介紹C# WinForm多執行緒開發之Thread類別庫,並提供簡單的範例程式碼供參考。

Windows是一個多任務的系統,如果你使用的是windows 2000以上版本,你可以透過工作管理員查看目前系統運行的程式和進程。什麼是進程呢?當一個程式開始運行時,它就是一個進程,進程所指包括運行中的程式和程式所使用的記憶體和系統資源。而一個行程又是由多個執行緒所組成的,執行緒是程式中的一個執行流,每個執行緒都有自己的專有暫存器(棧指標、程式計數器等),但程式碼區是共享的,即不同的線程可以執行同樣的函數。多執行緒是指程式中包含多個執行流,即在一個程式中可以同時執行多個不同的執行緒來執行不同的任務,也就是說允許單一程式建立多個並行執行的執行緒來完成各自的任務。

一 關於Thread的說明

在.net framework class library中,所有與多執行緒機制應用相關的類別都是放在System.Threading命名空間中的。其中提供Thread類別用於建立線程,ThreadPool類別用於管理線程池等等,此外還提供解決了線程執行安排,死鎖,線程間通訊等實際問題的機制。如果你想在你的應用程式中使用多線程,就必須包含這個類別。 Thread類別有幾個至關重要的方法,描述如下:

  • Start():啟動執行緒 

  • Sleep(int):靜態方法,暫停目前執行緒指定的毫秒數 

  • Abort():通常使用該方法來終止一個線程 

  • Suspend():該方法並不會終止未完成的線程,它只是掛起線程,以後還可恢復。

  • Resume():恢復被Suspend()方法掛起的線程的執行 

線程入口讓程式知道該讓這個執行緒做什麼事,在C#中,執行緒入口是透過ThreadStart代理(delegate)來提供的,你可以把ThreadStart理解為一個函數指針,指向執行緒要執行的函數,當調用Thread.Start ()方法後,執行緒就開始執行ThreadStart所代表或說指向的函數。 ThreadState在各種情況下的可能取值如下:

  • Aborted:執行緒已停止 

  • AbortRequested:線程的Thread.Abort()方法已被調用,但是線程還未停止 

  • Background:線程在後台執行,與屬性Thread.IsBackground有關 

  • Running:執行緒正在正常運作 

  • Stopped: 線程已經被停止 

  • StopRequested:線程正在被要求停止 

  • Suspended:執行緒已經被掛起(此狀態下,可以透過呼叫Resume()方法重新運行) 

  • SuspendRequested:執行緒正在要求被掛起,但是未來得及回應 

  • Unstarted:未呼叫Thread.Start()開始執行緒的執行 

  • WaitSleepJoin:執行緒因為呼叫了Wait(),Sleep()或Join()等方法處於封鎖狀態 


二Winform中使用的thread

首先可以看看最直接的方法,也是.net 1.0下支援的方法。但請注意的是,此方法在.net 2.0以後就已經是一種錯誤的方法了。


public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }
    private void Form1_Load(object sender, EventArgs e)
    {
        Thread thread = new Thread(ThreadFuntion);
        thread.IsBackground = true;
        thread.Start();
    }
    private void ThreadFuntion()
    {
        while (true)
        {
            this.textBox1.Text = DateTime.Now.ToString();
            Thread.Sleep(1000);
        }
    }
}

這段code 在vs2005或2008上都拋出例外:Cross-thread operation not valid:Control 'textBox1' accessed from a thread other than the thread it was created on . 這是因為.net 2.0以後加強了安全機制,不允許在winform中直接跨線程訪問控件的屬性。那麼要怎麼解決這個問題呢,下面提供幾種方案。


第一個方案: 在Thread創建之氣,將Control.CheckForIllegalCrossThreadCalls 設為 false。 此程式碼告訴編譯器:在這個類別中我們不檢查跨執行緒的呼叫是否合法(如果沒有加上這句話運行也沒有異常,那麼說明系統以及預設的採用了不檢查的方式)。然而,這種方法不可取。我們查看CheckForIllegalCrossThreadCalls 這個屬性的定義,就會發現它是一個static的,也就是說無論我們在專案的什麼地方修改了這個值,他就會在全局運作。而且像這種跨執行緒存取是否有異常,我們通常都會去檢查。如果專案中其他人修改了這個屬性,那麼我們的方案就失敗了,我們要採取另外的方案。

第二種方案

namespace TestInvoker
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void button1_Click(object sender, EventArgs e)
        {
            Thread thread = new Thread(new ThreadStart(StartSomeWorkFromUIThread));
            thread.IsBackground = true;
            thread.Start();
            //StartSomeWorkFromUIThread();
            //label1.Text = "Set value through another thread!";
        }
        private void StartSomeWorkFromUIThread()
        {
            if (this.InvokeRequired)
            {
                BeginInvoke(new EventHandler(RunsOnWorkerThread), null);
            }
            else
            {
                RunsOnWorkerThread(this, null);
            }
        }
        private void RunsOnWorkerThread(object sender, EventArgs e)
        {
            Thread.Sleep(2000);
            label1.Text = System.DateTime.Now.ToString();
        }
    }
}

透過上敘程式碼,可以看到問題已經解決了,透過等待非同步,我們就不會總是持有主執行緒的控制,這樣就可以在不發生跨執行緒呼叫異常的情況下完成多執行緒對winform多執行緒控制項的控制了。

 以上就是C# WinForm多執行緒開發(一) Thread類別函式庫的內容,更多相關內容請關注PHP中文網(www.php.cn)!


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