日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > C# >内容正文

C#

C#线程--5.0之前时代(一)--- 原理和基本使用

發布時間:2025/4/14 C# 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C#线程--5.0之前时代(一)--- 原理和基本使用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、開篇概念明晰:

多任務

  • 協作式多任務:cpu可以處理多種任務,但是這些任務是排隊等候的,當cpu在處理一個任務的時候,其他的任務被鎖定,只有當cpu處理完當前任務,才可以繼續處理下一個任務(專一暖男);
  • 搶占式多任務:一個任務正在執行,可以被強行中斷掛起,去執行其他的任務(花心大蘿卜)。

進程與線程:

  • 進程:內存和資源的物理分離成為進程。分配給進程的內存只有所屬的進程才可以訪問。一個應用程序可以啟動多個進程
  • 線程:開發架構將程序中的一部分進行分離,使被分離的部分與程序的其余部分執行順序不一致的操作。(在計算機中,程序的運行時由程序計數器決定的,程序計數器就像是一個指針,指定了應用程序下一步需要執行的指令。)
  • 進程與線程:一個進程啟動,默認會有一個主線程,但是一個進程可以對應多個線程。
  • 時間片:處理器分配給線程的執行時間。一個處理器一次只能處理一個線程,所謂的多任務(搶占式)就是處理器在快速切換執行不同的線程。若是有多個處理器就不一樣了。(自我入宮以來以為可以獨得皇上寵愛,沒想到皇上要雨露均沾)。

中斷:

前置知識點:

1、進程是內存和資源的物理分離,只有所屬線程才能訪問;

2、一個cpu給一次只能執行一個線程,cpu給每一個線程分配時間片,多線程就是在不同線程之間快速切換。

問題:進程間相互獨立且不可訪問,那么,cpu是怎么進行線程切換的,也就是問:一個線程正在執行,它要怎么知道要中斷掛起,給其他線程來執行。

答案:Windows本身(其實也是處理器上正在運行的一個程序)有一個主線程----系統線程,負責其他線程的調度。

線程本地存儲器(Thread Local Storage,TLS):存儲線程的狀態信息。當一個線程執行的時間片到期的時候,需要存儲下線程當前的狀態信息,以確保在他被分配的下一個時間片可以正常的執行。TLS包含了:

寄存器、堆棧指針、調度信息、內存中的地址空間和其他資源的使用信息。

其中寄存器中有一個是程序計數器,存放了線程接下來應該執行的指令。(CPU執行的指令的都是從寄存器讀取的)

中斷:中斷是一種機制,它能夠使CPU指令的正常順序執行轉向計算機內存中的其他地方,而不需要知道目前正在執行什么程序。解釋如下:

1、程序要開始執行一個線程之前:系統線程先決定線程要執行多長時間,and在當前線程的執行序列中放置一條中斷指令。疑問:不確定這個指令是在時間片到了之后插入的還是在線程開始之前預先插入的,但推測是等待時間片要到的時候插入的,因為程序執行的指令并不是容易預測的,不同的數據不同走不同的邏輯分支,程序的執行是一邊編一邊走的(會先編譯的快一些)而不是編譯好所有的邏輯分支的指令,等待程序執行的時候根據數據進行選擇,所以個人覺得很難預測要走哪一個邏輯分支,很難提前太早插入中斷指令。

2、程序開始執行一個線程:讀取TLS中線程的程序計數器,把該程序計數器的指令指向的地址從TLS中拖拽出來插入到CPU執行的指令集合中,同時把TLS中的堆棧信息加載到CPU的其他寄存器中。線程開始執行

3、當碰到中斷指令時:存儲當前線程的堆棧信息,記錄當前線程的程序計數器數據,記錄其他資源的信息,存儲入TLS,把當前線程放入線程隊列的末尾,返回到線程隊列的開頭準備執行隊列的第一個線程,回到步驟1。

線程睡眠:線程退出執行隊列一段時間稱為睡眠。有時一個線程的執行需要一定的資源,但是當線程開始執行時,這個資源并沒有生成或者正在被使用,因此線程需要等待一段時間。

時鐘中斷:一個線程進入睡眠是它會再次被打包放入TLS中,不過并不是放置在了TLS的末尾,而是放入了一個獨立的睡眠隊列中,為了時睡眠隊列上的線程再次運行,需要使用另一種中斷了標記他們,成為時鐘中斷。當一個睡眠的線程可以執行的時候,它才會被放入到可運行的線程隊列中,的末尾。

?線程終止:

  • 線程執行結束,線程終止;
  • 在執行另外一個線程的過程中,用一個請求顯示的停止線程。
  • 線程終止時,線程的TLS會釋放其內存。

    ?

    二、線程的創建:
    直接貼代碼:

    1、創建線程:

    2、使用線程創建線程:

    public override void DoExecute(){base.DoExecute();Thread mainThread = new Thread(new ThreadStart(MainThread));AddLog("current main thread's state is " + mainThread.ThreadState);mainThread.Start();AddLog("current main thread's state is " + mainThread.ThreadState);}private void FirstThread(){AddLog("FirstThread start~");for (int i = 0; i < 100; i++){AddLog("FirstThread index~ "+i);}AddLog("FirstThread stop~");}private void ThecondThread(){AddLog("ThecondThread start~");for (int i = 100; i < 200; i++){AddLog("ThecondThread index~ " + i);}AddLog("ThecondThread stop~");}private void MainThread(){AddLog("MainThread start~");Thread firstThread = new Thread(new ThreadStart(FirstThread));Thread secondThread = new Thread(new ThreadStart(ThecondThread));firstThread.Start();secondThread.Start();for (int i = 0; i < 100000; i++){}AddLog("thecondThread state " + secondThread.ThreadState);AddLog("MainThread stop~");}

    ?3、線程的睡眠和恢復:

    使用屬性:

    ThreadState:ThreadState是一個枚舉類型,表示線程的當前狀態,當線程睡眠的時候線程狀態值為ThreadState.WaitSleepJoin;

    ?注意一個類似的屬性:IsAlive (獲取指示當前線程的執行狀態的值)如果此線程已經開始但尚未正常終止或中止,則為 true,否則為 false。所以當線程睡眠的時候,isAlive仍然為true;

    使用方法:

    • Sleep(int millisecondsTimeout);? ?millisecondsTimeout表示使線程睡眠的毫秒數;
    • Interrupt();? ? ? 中斷處于 WaitSleepJoin 線程狀態的線程。

    ?測試代碼:

    public static void SleepThread(){Thread newThread = new Thread(new ThreadStart(PrintNo));newThread.Name = "new thread";newThread.Start();while (true){if (newThread.ThreadState == ThreadState.WaitSleepJoin){Console.WriteLine("current thread state: " + newThread.ThreadState);newThread.Interrupt();break;}}}static void PrintNo(){for (int i = 0; i < 99; i++){Console.WriteLine("print " + i);if (i == 90){
                //
    try {Thread.Sleep(2000);}catch (Exception ex){Console.WriteLine("new thread interrupted"+ex.Message);}Console.WriteLine("current thread is " + Thread.CurrentThread.Name + ", state: " + Thread.CurrentThread.ThreadState);}}}

    結果:

    ... print 81 print 82 print 83 print 84 print 85 print 86 print 87 print 88 print 89 print 90 current thread state: WaitSleepJoin new thread interrupted current thread is new thread, state: Running print 91 print 92 print 93 print 94 print 95 print 96 print 97 print 98

    Interrupt() 是對睡眠的線程提前喚醒的最好方法,需要注意的是使用這個方法會拋出異常需要捕獲。

    4、線程的中止(終止)和取消中止(終止):

    使用方法:

    • Thread.CurrentThread.Abort(); 終止當前線程 --- 調用該方法線程將進入正在終止狀態 ------? AbortRequested,
    • Thread.ResetAbort();? 取消當前線程Abort的請求使線程繼續執行。調用該方法線程將恢復
    public static void AbortThread(){Thread newThread = new Thread(new ThreadStart(PrintNo));newThread.Name = "new thread for abort";newThread.Start();}static void PrintNo(){for (int i = 0; i < 99; i++){Console.WriteLine("print " + i);if (i == 90){try{Thread.CurrentThread.Abort(); // 中斷當前線程,會引發異常 }catch (Exception ex){Console.WriteLine("current thread is " + Thread.CurrentThread.Name + ", state: " + Thread.CurrentThread.ThreadState);Console.WriteLine("new thread Aborted" + ex.Message);// 取消當前線程請求的Abort(); //Thread.ResetAbort(); }Console.WriteLine("current thread is " + Thread.CurrentThread.Name + ", state: " + Thread.CurrentThread.ThreadState);}}}

    ?

    運行結果:

    。。。
    print 87
    print 88
    print 89
    print 90
    current thread is new thread for abort, state: AbortRequested
    new thread Aborted正在中止線程。

    ?如果取消上面對 Thread.ResetAbort(); 的注釋,線程將不會終止,而是會繼續執行。

    ?

    5、使用join:
    使用方法:join(),join是線程實例上的方法,當調用該方法的時候調用該方法的線程實例將進入WaitSleepJoin狀態,直到當前線程執行完畢之后才開始繼續執行線程實例所屬的線程。
    (我感覺理解起來有點繞,意思就是:有兩個線程A和B,線程A需要在線程B之前執行,那么可以使用Join方法,在線程A內用線程B調用Join方法,這樣可以使線程B進入WaitSleepJoin狀態,線程A不變繼續執行,當線程A執行完畢,B會開始執行。而如果有線程C,則線程C是不影響的)如下所示:

    class ThreadTestForJoin{static Thread newThread;static Thread newThread2;static Thread newThread3;public static void JoinThread(){newThread = new Thread(new ThreadStart(PrintNo));newThread.Name = "new thread for join";newThread.Start();newThread2 = new Thread(new ThreadStart(PrintNo2));newThread2.Name = "new thread be joined";newThread2.Start();newThread3 = new Thread(new ThreadStart(PrintThreadThree));newThread3.Name = "我是勤勞的小畫家";newThread3.Start();}static void PrintNo(){for (int i = 0; i < 10; i++){Console.WriteLine("print " + i);}}static void PrintNo2(){newThread.Join();for (int i = 100; i < 199; i++){Console.WriteLine("print " + i);}}static void PrintThreadThree(){for (int i = 0; i < 200; i++){Console.WriteLine("print " + Thread.CurrentThread.Name);}}}

    運行結果:

    。。。 print 我是勤勞的小畫家 print 我是勤勞的小畫家 print 我是勤勞的小畫家 print 92 print 93 print 94 print 95 print 96 print 97 print 98 print 99 print 我是勤勞的小畫家 print 我是勤勞的小畫家 print 我是勤勞的小畫家 print 我是勤勞的小畫家 print 100 print 101 print 102 。。。

    ?

    轉載于:https://www.cnblogs.com/heisehenbai/p/9221444.html

    總結

    以上是生活随笔為你收集整理的C#线程--5.0之前时代(一)--- 原理和基本使用的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。