程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> c#線程Thread示例

c#線程Thread示例

編輯:C#入門知識

c#線程Thread示例。本站提示廣大學習愛好者:(c#線程Thread示例)文章只能為提供參考,不一定能成為您想要的結果。以下是c#線程Thread示例正文


C#是一門支撐多線程的說話,是以線程的應用也是比擬罕見的。因為線程的常識在Win32編程的時刻曾經說得過量,所以在.Net中很少引見這部門(能夠.Net不認為這部門是它所獨有的)。

那末線程相干的成績年夜致有以下四類(這篇文章只評論辯論單線程、單線程與UI線程這兩方面的成績)。
成績一,線程的根本操作,例如:暫停、持續、停滯等;
成績二,若何向線程傳遞參數或許從中獲得其前往值;
成績三,若何使線程所占用的CPU不要總是百分之百;
最初一個,也是成績最多的,就是若何在子線程來掌握UI中的控件,換句話說,就是在線程中掌握窗體某些控件的顯示。

關於成績一,我不建議應用Thread類供給的Suspend、Resume和Abort這三個辦法,前兩個有成績,似乎在VS05曾經屏障這兩個辦法;關於Abort來講,除資本沒有獲得實時釋放外,有時刻會湧現異常。若何做呢,經由過程設置開關變量來完成。

關於成績二,我不建議應用靜態成員來完成,僅僅為了線程而損壞類的封裝有些得失相當。那若何做呢,經由過程創立零丁的線程類來完成。

關於成績三來講,形成這個緣由是因為線程中停止不連續的輪回操作,從而使CPU完整被子線程占領。那末處置此類成績,其實很簡略,在恰當的地位挪用Thread.Sleep(20)來釋放所占領CPU資本,不要小視這20毫秒的睡眠,它的感化可是偉大的,可使其他線程獲得CPU資本,從而使你的CPU應用效力降上去。

看完後面的三個成績的說明,關於若何做仿佛沒有給出一個明白的謎底,為了更好地解釋若何處理這三個成績,我用一個比擬完全的例子展示給年夜家,代碼以下。


//--------------------------- Sub-thread class ---------------------------------------
//------------------------------------------------------------------------------------
//---File:          clsSubThread
//---Description:   The sub-thread template class file
//---Author:        Knight
//------------------------------------------------------------------------------------
//---------------------------{Sub-thread class}---------------------------------------
namespace ThreadTemplate
{
using System;
using System.Threading;
using System.IO;
/// <summary>
/// Summary description for clsSubThread.
/// </summary>
public class clsSubThread:IDisposable
{
private Thread thdSubThread = null;
private Mutex mUnique = new Mutex();

private bool blnIsStopped;
private bool blnSuspended;
private bool blnStarted;
private int nStartNum;

public bool IsStopped
{
get{ return blnIsStopped; }
}
public bool IsSuspended
{
get{ return blnSuspended; }
}
public int ReturnValue
{
get{ return nStartNum;}
}

  
public clsSubThread( int StartNum )
{
//
// TODO: Add constructor logic here
//
blnIsStopped = true;
blnSuspended = false;
blnStarted = false;

nStartNum = StartNum;
}

/// <summary>
/// Start sub-thread
/// </summary>
public void Start()
{
if( !blnStarted )
{
thdSubThread = new Thread( new ThreadStart( SubThread ) );
blnIsStopped = false;
blnStarted = true;
thdSubThread.Start();
}
}

/// <summary>
/// Thread entry function
/// </summary>
private void SubThread()
{
do
{
// Wait for resume-command if got suspend-command here
mUnique.WaitOne();
mUnique.ReleaseMutex();

nStartNum++;

Thread.Sleep(1000); // Release CPU here
}while( blnIsStopped == false );
}

/// <summary>
/// Suspend sub-thread
/// </summary>
public void Suspend()
{
if( blnStarted && !blnSuspended )
{
blnSuspended = true;
mUnique.WaitOne();
}
}

/// <summary>
/// Resume sub-thread
/// </summary>
public void Resume()
{
if( blnStarted && blnSuspended )
{
blnSuspended = false;
mUnique.ReleaseMutex();
}
}

/// <summary>
/// Stop sub-thread
/// </summary>
public void Stop()
{
if( blnStarted )
{
if( blnSuspended )
Resume();

blnStarted = false;
blnIsStopped = true;
thdSubThread.Join();
}
}
#region IDisposable Members
/// <summary>
/// Class resources dispose here
/// </summary>
public void Dispose()
{
// TODO:  Add clsSubThread.Dispose implementation
Stop();//Stop thread first
GC.SuppressFinalize( this );
}

#endregion
}
}

那末關於挪用呢,就異常簡略了,以下:
// Create new sub-thread object with parameters
clsSubThread mySubThread = new clsSubThread( 5 );

mySubThread.Start();//Start thread

Thread.Sleep( 2000 );
mySubThread.Suspend();//Suspend thread

Thread.Sleep( 2000 );
mySubThread.Resume();//Resume thread

Thread.Sleep( 2000 );
mySubThread.Stop();//Stop thread

//Get thread's return value
Debug.WriteLine( mySubThread.ReturnValue );

//Release sub-thread object
mySubThread.Dispose();

在回過火來看看後面所說的三個成績。
關於成績一來講,起首須要部分成員的支撐,那末
private Mutex mUnique = new Mutex();

private bool blnIsStopped;
private bool blnSuspended;
private bool blnStarted;

光算作員稱號,估量年夜家都曾經猜出其代表的意思。接上去須要修正線程進口函數,如果這些開關變量能施展感化,那末看看SubThread這個函數。
/// <summary>
/// Thread entry function
/// </summary>
private void SubThread()
{
do
{
// Wait for resume-command if got suspend-command here
mUnique.WaitOne();
mUnique.ReleaseMutex();

nStartNum++;

Thread.Sleep(1000);
}while( blnIsStopped == false );
}

函數比擬簡略,不到十句,能夠關於“blnIsStopped == false”這個斷定來講,年夜家還比擬好懂得,這是一個通俗的斷定,假如以後Stop開關翻開了,就停滯輪回;不然一向輪回。
年夜家比擬困惑的能夠是以下這兩句:
mUnique.WaitOne();
mUnique.ReleaseMutex();
這兩句的目標是為了使線程在Suspend操作的時刻能施展後果,為懂得釋這兩句,須要聯合Suspend和Resume這兩個辦法,它倆的代碼以下。
/// <summary>
/// Suspend sub-thread
/// </summary>
public void Suspend()
{
if( blnStarted && !blnSuspended )
{
blnSuspended = true;
mUnique.WaitOne();
}
}

/// <summary>
/// Resume sub-thread
/// </summary>
public void Resume()
{
if( blnStarted && blnSuspended )
{
blnSuspended = false;
mUnique.ReleaseMutex();
}
}


為了更好地解釋,還須要先簡略說說Mutex類型。關於此類型對象,當挪用對象的WaitOne以後,假如此時沒有其他線程對它應用的時刻,就連忙取得旌旗燈號量,持續履行代碼;當再挪用ReleaseMutex之前,假如再挪用對象的WaitOne辦法,就會一向期待,直到取得旌旗燈號量的挪用ReleaseMutex來停止釋放。這就比如洗手間的應用,假如沒有人應用則可以直接應用,不然只要期待。
明確了這一點後,再來說明這兩句所能湧現的景象。

mUnique.WaitOne();
mUnique.ReleaseMutex();


當在線程函數中,履行到“mUnique.WaitOne();”這一句的時刻,假如此時外界沒有發送Suspend新聞,也就是旌旗燈號量沒有被占用,那末這一句可以連忙前往。那末為何要緊接著釋放呢,由於不克不及總占著旌旗燈號量,立刻釋放旌旗燈號量是防止在發送Suspend敕令的時刻湧現期待;假如此時外界曾經發送了Suspend新聞,也就是說旌旗燈號量曾經被占用,此時“mUnique.WaitOne();”不克不及連忙前往,須要比及旌旗燈號量被釋放能力持續停止,也就是須要挪用Resume的時刻,“mUnique.WaitOne();”能力取得旌旗燈號量停止持續履行。如許能力到達真正意義上的Suspend和Resume。

至於線程的Start和Stop來講,絕對比擬簡略,這裡我就不多說了。

如今再來剖析一下成績二,其實例子比擬顯著,是經由過程結構函數和屬性來完成參數和前往值,這一點我也不多說了。假如線程參數比擬多的話,可以斟酌屬性來完成,相似於前往值。

成績三,我就更不消多說了。有人說了,假如子線程中的輪回不克不及睡眠怎樣辦,由於睡眠的話,有時會形成數據喪失,這方面的可以自創後面Suspend的做法,假如更龐雜,則牽扯到多線程的同步成績,這部門我會稍後零丁寫一篇文章。

前三個成績處理了,該說說最多見的成績,若何在子線程中掌握窗體控件。這也是寫線程方面法式常常碰到的。

起首說說,為何不克不及直接在子線程中把持UI呢。緣由在於子線程和UI線程屬於分歧的高低文,換句比擬淺顯的話說,就比如兩小我在分歧的房間裡一樣,那末要你直接操作另外一個房間裡的器械,生怕不可罷,那末關於子線程來講也一樣,不克不及直接操作UI線程中的對象。

那末若何在子線程中把持UI線程中的對象呢,.Net供給了Invoke和BeginInvoke這兩種辦法。簡略地說,就是子線程發新聞讓UI線程來完成響應的操作。

這兩個辦法有甚麼差別,這在我之前的文章曾經說過了,Invoke須要比及所調函數的前往,而BeginInvoke則不須要。

用這兩個辦法須要留意的,有以下三點:
第一個是因為Invoke和BeginInvoke屬於Control類型的成員辦法,是以挪用的時刻,須要獲得Control類型的對象能力觸發,也就是說你要觸發窗體做甚麼操作或許窗體上某個控件做甚麼操作,須要把窗體對象或許控件對象傳遞到線程中。

第二個,關於Invoke和BeginInvoke接收的參數屬於一個delegate類型,我在之前的文章中應用的是MethodInvoker,這是.Net自帶的一個delegate類型,而其實不意味著在應用Invoke或許BeginInvoke的時刻只能用它。參看我給的第二篇文章(《若何彈出一個形式窗口來顯示進度條》),會有許多分歧的delegate界說。

最初一個,應用Invoke和BeginInvoke有個須要留意的,就是當子線程在Form_Load開啟的時刻,會碰到異常,這是由於觸發Invoke的對象還沒有完整初始化終了。處置此類成績,在開啟線程之前顯式的挪用“this.Show();”,來使窗體顯示在線程開啟之前。假如此時只是開啟線程來初始化顯示數據,那我建議你不要應用子線程,用Splash窗體的後果能夠更好。
線程的四個相干成績曾經說完了,這篇文章只說了單線程,和單線程與UI線程交互的成績。個中觸及到的辦法紛歧定是獨一的,由於.Net還供給了其他類來扶直線程操作,這裡就紛歧一枚舉。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved