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多線程控件的控制了。

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM