多線程學習筆記第一篇

來源:互聯網
上載者:User

1. 多線程

  (1) 進程(Process):是WIndows系統中的一個基本概念,它包含著一個運行程式所需要的資源,進程之間是相對獨立的,一個進程無法直接存取另一個進程的資料(除非利用分散式運算方法),一個進程啟動並執行失敗也不會影響其他進程的運行,windows系統就是利用進程把工作劃分為多個獨立的地區,進程可以理解為一個程式的基本邊界。

       1)要解 決的問題:為了使程式能夠並發執行(要並發處理就要隔離進程,使進程獨立,即每個進程有屬於自己的資料區段,程式段,進程式控制制塊)

       2)進程是隔離不同應用程式的一種資源

       3)進程Demo,代碼如下:

              static void Main(string[] args)

              {

                     //操作進程:GetCurrentProcess讀取當前進程

                     Console.WriteLine(Process.GetCurrentProcess());

                     //擷取作業系統中的所有進程

                     var process = Process.GetProcesses();

                     foreach (var item in process)

                     {

                            //輸出所有作業系統的名稱

                            Console.WriteLine(item.ProcessName);

                     }

                     //開啟一個應用程式的進程

                     Process.Start("iexplore.exe", "http://www.cnblogs.com/hanyinglong");

                     var p = Process.Start("notepad.exe");

                    //殺掉一個線程

                     Thread.Sleep(3000);

                     p.Kill();

             }

  (2) 線程:線程就是一個程式碼片段的執行流

       1)是Windows任務調度的最小單位,線程是程式中的一個執行流,每個線程都有自己的專有寄存器(棧指標,程式計數器等),但代碼區是共用的,即不同的線程可以執行同樣的函數。

       2)解決問題:進程是一個資源的擁有者,因為在進程的建立,撤銷和切換的過程中,系統必須為自付出比較大的開銷,限制了並發程式的進一步提高

       3)一個進程可以有多個線程

       4)CPU的核心切換的是線程

       5)作業系統:一個CPU同一時間只能執行一個線程,多核,

      6)作業系統切換線程的時候需要將線程的資源,狀態都要儲存起來。

       7)線程建立的時候需要線程的控制塊(1M),線程棧,線程寄存器。

 (3) Managed 程式碼和Unmanaged 程式碼的區別

    

  (4) 線程Demo,建立一個控制台應用程式,代碼如下:

namespace ThreadDemo{      //當前這個程式的代碼是執行在主線程上面的      class Program      {            static void Main(string[] args)             {                      //列印出當前主線程的資訊                      Thread currentThread= Thread.CurrentThread;                      //列印出主線程的ID,ManagedThreadId是託管線程的一個唯一編號                      Console.WriteLine("當前預設的主線程的ID是" + currentThread.ManagedThreadId);                      //建立一個線程,傳遞一個ThreadStart參數,這個參數轉到定義可以看到是一個委託                       //建立一個線程對象,並沒有真正的分配線程                       Thread threadDemo = new Thread(ThreadDemoMethod);                       //只有調用此方法的時候,才是真正的告訴作業系統線程準備好,請作業系統分配線程並且執行                       threadDemo.Start();  //啟動線程來執行                       Console.WriteLine("主線程執行結束");                       Console.ReadKey();              }                static void ThreadDemoMethod()                {                       Console.WriteLine("另一個線程正在執行,線程的ID是{0}", Thread.CurrentThread.ManagedThreadId);                }          }  }

       這段代碼的執行結果是:

              當前預設的主線程的ID是1

              主線程執行結束

             另一個線程正在執行,線程的ID是3

  (5) 應用程式定義域

    1)它提供安全而通用的處理單元,公用語言運行庫(CLR)可以使用它來提供應用程式之間的隔離。您可以在具有同等隔離等級(存在於單獨的進程中)的單個進程中運行幾個應用程式定義域,而不會造成進程間調用或者進程間切換等方面的額外開銷,在一個進程內運行多個應用程式的能力顯著增強了伺服器的延展性

       2)應用程式定義域裡面有記憶體配置的堆,也提供了一種代碼安全的邊界(兩個應用程式定義域之間的代碼是相互隔離的),提供了異常的處理

       3)一個應用程式定義域可以跑多個線程

       4)一個線程同一時間只能運行在一個應用程式定義域中,但是一個應用程式定義域可以同時擁有多個線程

       5)應用程式定義域Demo

              static void Main(string[] args)

              {

                     //列印當前應用程式定義域

                     Console.WriteLine(AppDomain.CurrentDomain.FriendlyName);

                     //建立應用程式定義域

                     AppDomain domainDemo = AppDomain.CreateDomain("韓迎龍");

                     //讓當前應用程式定義域啟動執行一個exe程式(可以包含執行一個exe,但是可以有多個程式集dll)

                     //第一步:將其他項目中的exe檔案和pdf檔案拷貝一份放到我們這個項目下面

                     //第二步:將上面拷貝進來的exe檔案右鍵屬性,修改複製到輸出目錄為始終複製

                    domainDemo.ExecuteAssembly("搖獎機.exe");

             }

      6)執行結果,:

      

  (6) 簡單線程詳細說明

    1)線程的調度是由作業系統來操作的,我們的操作只是建議

       2)threadDemo.IsBackground = true;

             -> 設定當前線程的一個類型,預設是前台線程

         -> true代表設定一個後台線程,當前台線程都關閉之後,當前進程就直接關閉了

         -> false代表設定一個前台線程,

       3)線程設定Demo

            class Program            {                   static void Main(string[] args)                   {                          Thread threadDemo = new Thread(DemoThreadMethod);                          //設定當前線程的優先順序,只是建議作業系統,給我當前的這個線程,優先順序高點                          threadDemo.Priority = ThreadPriority.Highest;                          //如果設定成前台線程,那麼就必須當前線程執行完畢之後,整個進程才會推出                          threadDemo.IsBackground = true;                          threadDemo.Start();                          Thread.Sleep(3000);                          //關閉線程                          //threadDemo.Abort();                          //將當前執行此代碼的線程阻塞,等待線程執行完畢                          threadDemo.Join(1000);                          //給線程起一個名字                          threadDemo.Name = "線程";                          Console.WriteLine("主線程執行完畢");                   }                   static void DemoThreadMethod()                   {                          while (true)                          {                                 Console.WriteLine(DateTime.Now.ToString());                          }                   }            }

  (7) 帶參數的線程說明

    1)ParameterizedThreadStart執行方法

              ->查看Reflect: public delegate void ParameterizedThreadStart(object obj);

       2)線程的委託都是沒有傳回值的,因為我們不知道線程什麼時候結束

       3)帶參數的線程Demo

            class Program

            {

                   static void Main(string[] args)

                   {

                          //啟動一個帶參數的線程

                          Thread threadDemo = new Thread(DemoParamets);

                          //給線程指定的方法傳遞參數

                          //可以傳遞數組

                          threadDemo.Start("韓迎龍");

                          Thread.Sleep(2000);

                          Console.ReadKey();

                   }

                     static void DemoParamets(object data)

                   {

                          Console.WriteLine(data.ToString());

                   }

            }

     4)將上面這段代碼在Reflect中查看代碼::

    

2. 線程中如何訪問控制項

  (1) 建立一個Winform應用程式,起名為:MultiThread,給這個建立的WinForm表單添加一個文字框控制項和一個Button按鈕

  (2)Demo代碼

     public partial class Form1 : Form     {            public Form1()            {                   InitializeComponent();                   //如果不寫的話會報這個錯誤:線程間操作無效: 從不是建立控制項“txtMSg”的線程訪問它。                   //還有一種方式解決將在下面說到                   Control.CheckForIllegalCrossThreadCalls = false;             }            private void btnThread_Click(object sender, EventArgs e)            {                   //這是一種寫法                   //new Thread(() =>                   //{                   //    txtMSg.Text = DateTime.Now.ToString();                   //}).Start();                   //第二種說法                   Thread thread = new Thread(ChangeTxt);                   thread.Start();            }            public void ChangeTxt()            {                   txtMSg.Text = DateTime.Now.ToString();            }     }

3. 使用委託實現兩個介面之間資料的互動案例

  (1) 建立一個Winform程式,將Form1表單作為主表單,在建立一個表單作為子表單,給父表單添加一個Button和一個TextBox控制項。給子表單中添加一個Button控制項和一個TextBox控制項,項目樣式在後面有:

 (2)主表單中的代碼如下:     public partial class Form1 : Form     {            public Form1()            {                   InitializeComponent();                   //如果不寫的話會報這個錯誤:線程間操作無效: 從不是建立控制項“txtMSg”的線程訪問它。                   //還有一種方式解決將在下面說到                   Control.CheckForIllegalCrossThreadCalls = false;               }            private void btnThread_Click(object sender, EventArgs e)            {                     while (true)                   {                          Thread thread = new Thread(ChangeTxt);                          thread.Start();                   }            }            public void ChangeTxt()            {                   txtMSg.Text = DateTime.Now.ToString();            }            private void btnStart_Click(object sender, EventArgs e)            {                   //使用委託實現                   FrmChild frm = new FrmChild();                   //把當前主表單的應用添加到this中                   frm.ParentFrm = this;                   frm.AfterTxtChange = new SetTextDel(SetText);                   frm.Show();            }            //添加一個方法給主表單的控制項賦值            public void SetText(string str)            {                   txtMSg.Text = str;            }     }(3)子表單中的代碼如下:     //使用委託實現這個功能     public delegate void SetTextDel(string str);     public partial class FrmChild : Form     {            //定義了一個父表單的變數            public Form1 ParentFrm;            //定義一個委託類的執行個體            public SetTextDel AfterTxtChange;            public FrmChild()            {                   InitializeComponent();            }            private void btnParent_Click(object sender, EventArgs e)            {                   string childtxt = txtChildMsg.Text;                   //第一種方法                   ////將值同步到主表單上面                   //this.ParentFrm.SetText(childtxt);                   //第二種方法                   AfterTxtChange(childtxt);            }     }

     (4)實現結果:

    

4. 總結

  (1) 為什麼要用多線程

       1)讓電腦"同時"做多件事情,節約能源。

       2)多線程可以讓一個程式"同時"處理多個事情。

       3)後台運行程式,提高程式的運行效率,也不會是主介面出現無響應的情況

  (2)產生一個線程的四個步驟

       1)編寫產生線程所要執行的方法。

       2)引入System.Threading命名空間。

       3)執行個體化Thread類,並傳入一個指向線程所要運行方法的委託(這時候線程已經產生,但是還沒有運行)。

       4)調用Thread執行個體的Start方法,標記該線程可以被CPU執行了,但是具體的執行時間由CPU決定。

  (3)注意"方法重入"的問題

       1)所謂的方法重入,是一個有關多線程編程的概念,程式中多個線程同時運行時,就可能發生同一個方法被多個線程同時調用的情況,當這個方法中存在一些非安全執行緒的代碼,方法重入就會導致資料不一致的情況,這是一個嚴重的Bug。

  (4)進程和線程

       1)一個進程至少有一個線程

       2)同一個進程中的多個線程之間可以"並發"執行。

       3)線程是程式中的一個執行流,每個線程都有自己的專有寄存器(棧指標、程式計數器等),但代碼區是共用的,即不同的線程可以執行同樣的函數。多線程是指程式中包含多個執行流,即在一個程式中可以同時運行多個不同的線程來執行不同的任務(代碼),也就是說允許單個程式建立多個並存執行的線程來完成各自的任務。

  (5)前台線程和後台線程

       1)前台線程:只有所有的前台線程都關閉才能完成程式關閉。

       2)後台線程:只有所有的前台線程結束,後台線程自動結束。

  (6).NET中如何?多線程?

       1)線程肯定也是要執行一段代碼的。所以要產生一個線程,必須先為該線程寫一個方法,這個方法中的代碼就是該線程運行所要執行的代碼(找一個人來做這件事情)

       2)線程啟動時,通過委託調用該方法.(線程啟動時,調用傳過來的委託,委託就會執行相應的代碼,實現線程執行的方法)。

  (7)Thread類的一些成員

       1)Start()啟動線程

       2)Abort()終止線程

       3)Thread.Sleep(100)靜態方法,可以使當前線程停止一段時間在運行

       4)Name線程名稱

       5)Thread.CurrentThread獲得當前的線程引用

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.