淺解關於C#多線程的介紹

來源:互聯網
上載者:User

多線程的相關概念
--------------------------------------------------------------------------------
1.進程:是作業系統結構的基礎;是一個正在執行的程式;電腦中正在啟動並執行程式執行個體;可以分配給處理器並由處理器執行的一個實體;由單一順序的執行顯示,一個目前狀態和一組相關的系統資源所描述的活動單元。
2.線程:線程是程式中一個單一的順序控制流程程。是程式執行流的最小單元。另外,線程是進程中的一個實體,是被系統獨立調度和指派的基本單位,線程自己不擁有系統資源,只擁有一點在運行中必不可少的資源,但它可與同屬一個進程的其它線程共用進程所擁有的全部資源。一個線程可以建立和撤消另一個線程,同一進程中的多個線程之間可以並發執行。由於線程之間的相互制約,致使線程在運行中呈現出間斷性。線程也有就緒、阻塞和運行三種基本狀態。每一個程式都至少有一個線程,若程式只有一個線程,那就是程式本身。
3.多線程:在單個程式中同時運行多個線程完成不同的工作,稱為多線程。
--------------------------------------------------------------------------------
小結:其實更容易理解一點進程與線程的話,可以舉這樣一個例子:把進程理解成為一個運營著的公司,然而每一個公司員工就可以叫做一個進程。每個公司至少要有一個員工,員工越多,如果你的管理合理的話,公司的運營速度就會越好。這裡官味一點話就是說。cpu大部分時間處於空閑時間,浪費了cpu資源,多線程可以讓一個程式“同時”處理多個事情,提高效率。
--------------------------------------------------------------------------------
單線程問題示範
--------------------------------------------------------------------------------
建立一個WinForm應用程式,這裡出現的問題是,點擊按鈕後如果在彈出提示框之前,表單是不能被拖動的。

複製代碼 代碼如下:private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < 10000000000; i++)
{
i += 1;
}
MessageBox.Show("出現後能拖動,提示沒出現之前表單不能被拖動");
}

原因:運行這個應用程式的時候,表單應用程式內建一個叫做UI的線程,這個線程負責表單介面的移動大小等。如果點擊按鈕則這個線程就去處理這個迴圈計算,而放棄了其它操作,故而表單拖動無響應。這就是單線程帶來的問題。

解決辦法:使用多線程,我們自己建立線程。把計算代碼放入我們自己寫的線程中,UI線程就能繼續做他的介面響應了。
--------------------------------------------------------------------------------
線程的建立
--------------------------------------------------------------------------------

線程的實現:線程一定是要執行一段代碼的,所以要產生一個線程,必須先為該線程寫一個方法,這個方法中的代碼,就是該線程中要執行的代碼,然而啟動線程時,是通過委託調用該方法的。線程啟動是,調用傳過來的委託,委託就會執行相應的方法,從而實現線程執行方法。

複製代碼 代碼如下://建立線程
private void button1_Click(object sender, EventArgs e)
{
//ThreadStart是一個無參無傳回值的委託。
ThreadStart ts = new ThreadStart(js);
//初始化Thread的新執行個體,並通過構造方法將委託ts做為參數賦初始值。
Thread td = new Thread(ts); //需要引入System.Threading命名空間
//運行委託
td.Start();
}
//建立的線程要執行的函數。
void js()
{
for (int i = 0; i < 1000000000; i++)
{
i += 1;
}
MessageBox.Show("提示出現前後表單都能被拖動");
}

把這個計算寫入自己寫的線程中,就解決了單線程中的介面無反應缺陷。
--------------------------------------------------------------------------------
小結:建立線程的4個步驟:1.編寫線程索要執行的方法。2.引用System.Threading命名空。3.執行個體化Thread類,並傳入一個指向線程所要運行方法的委託。4.調用Start()方法,將該線程標記為可以啟動並執行狀態,但具體執行時間由cpu決定。
--------------------------------------------------------------------------------
方法重入(多個線程執行一個方法)
--------------------------------------------------------------------------------
由於線程可與同屬一個進程的其它線程共用進程所擁有的全部資源。

所以多個線程同時執行一個方法的情況是存在的,然而這裡不經過處理的話會出現一點問題,線程之間先後爭搶資源,致使資料計算結果錯亂。

複製代碼 代碼如下:public partial class 方法重入 : Form
{
public 方法重入()
{
InitializeComponent();

//設定TextBox類的這個屬性是因為,開啟ui線程,
//微軟設定檢測不允許其它線程對ui線程的資料進行訪問,這裡我們把檢測關閉,也就允許了其它線程對ui線程資料的訪問。
//如果檢測不設定為False,則報錯。
TextBox.CheckForIllegalCrossThreadCalls = false;
}

private void button1_Click(object sender, EventArgs e)
{
textBox1.Text = "0";
//開啟第一個線程,對js方法進行計算
ThreadStart ts = new ThreadStart(js);
Thread td = new Thread(ts);
td.Start();

//開啟第二個線程,對js方法進行計算
ThreadStart ts1 = new ThreadStart(js);
Thread td1 = new Thread(ts1);
td1.Start();
}
//多線程要重入的方法。
void js()
{
int a = Convert.ToInt32(textBox1.Text);
for (int i = 0; i < 2000; i++)
{
a++;
textBox1.Text = a.ToString();
}
}
}

出錯現象:點擊按鈕後TextBox1中資料為2000+或2000,如果你看到的資料一直是2000說明你的電腦cpu比較牛X,這樣的話你想看到不是2000的話,你可以多點擊幾次試試,真不行的話,代碼中給TextBox1賦值為0,換做在介面中給textBox1數值預設值為0試試看。

出錯原因:兩個進程同時計算這個方法,不相干擾應該每個線程計算的結果都是2000的,但是這裡的結果輸出卻讓人以外,原因是第一個兩個線程同時計算,並不是同時開始計算,而是根據cpu決定的哪個先開始,哪個後開始,雖然相差時間不多,但後開始的就會取用先開始計算過的資料計算,這樣就會導致計算錯亂。

解決辦法:解決這個的一個簡單辦法解釋給方法加鎖,加鎖的意思就是第一個線程取用過這個資源完畢後,第二個線程再來取用此資源。形成排隊效果。

下面給方法加鎖。

複製代碼 代碼如下://多線程要重入的方法,這裡加鎖。
void js()
{
lock (this)
{
int a = Convert.ToInt32(textBox1.Text);
for (int i = 0; i < 2000; i++)
{
a++;
textBox1.Text = a.ToString();
}
}
}

給方法加過鎖後,線程一前一後取用資源,就能避免不可預計的錯亂結果,第一個線程計算為2000,第二個線程計算就是從2000開始,這裡的結果就為4000。
--------------------------------------------------------------------------------
小結:多線程可以同時運行,提高了cpu的效率,這裡的同時並不是同時開始,同時結束,他們的開始是由cpu決定的,時間相差不大,但會有不可預計的計算錯亂,這裡要注意類似上面例子導致的方法重入問題。
--------------------------------------------------------------------------------
前台線程後台線程
--------------------------------------------------------------------------------
.Net的公用語言運行時能區分兩種不同類型的線程:前台線程和後台線程。這兩者的區別就是:應用程式必須運行完所有的前台線程才可以退出;而對於後台線程,應用程式則可以不考慮其是否已經運行完畢而直接退出,所有的後台線程在應用程式退出時都會自動結束。

問題:關閉了視窗,訊息框還能彈出。

複製代碼 代碼如下:private void button1_Click(object sender, EventArgs e)
{
//開啟一個線程,對js方法進行計算
ThreadStart ts2 = new ThreadStart(js);
Thread td2 = new Thread(ts2);
td2.Start();

}
void js()
{
for (int i = 0; i < 2000000000; i++) //如果看不出效果這裡的2後面多加0
{
i++;
}
MessageBox.Show("關閉了視窗我還是要出來的!");
}

原因:.Net環境使用Thread建立線程,線程預設為前台線程。即線程屬性IsBackground=false,而前台線程只要有一個在運行則應用程式不關閉,所以知道彈出訊息框後應用程式才算關閉。

解決辦法:在代碼中設定td2.IsBackground=true;
--------------------------------------------------------------------------------
線程執行帶參數的方法
--------------------------------------------------------------------------------

複製代碼 代碼如下://建立一個執行帶參數方法的線程
private void button1_Click(object sender, EventArgs e)
{
//ParameterizedThreadStart這是一個參數類型為object的委託
ParameterizedThreadStart pts=new ParameterizedThreadStart(SayHello);
Thread td2 = new Thread(pts);
td2.Start("張三"); //參數值先入這裡
}
void SayHello(object name)
{
MessageBox.Show("你好,"+name.ToString()+"!");
}

線程執行帶多參數的方法
--------------------------------------------------------------------------------
其實還是帶一參數的方法,只不過是利用參數類型為object的好處,這裡將類型傳為list類型,貌似多參。複製代碼 代碼如下: //建立一個執行帶多個參數的方法線程
private void button1_Click(object sender, EventArgs e)
{
List<string> list = new List<string> { "張三", "李四", "王五" };
//ParameterizedThreadStart這是一個參數類型為object的委託
ParameterizedThreadStart pts=new ParameterizedThreadStart(SayHello);
Thread td2 = new Thread(pts);
td2.Start(list); //參數值先入這裡
}
void SayHello(object list)
{
List<string> lt = list as List<string>;
for (int i = 0; i < lt.Count; i++)
{
MessageBox.Show("你好," + lt[i].ToString() + "!");
}
}

總結:看到這裡相信對多線程應該有一個初步的瞭解了,我就不說了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.