亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C# > 正文

c#線程Thread示例

2020-01-24 02:41:12
字體:
來源:轉載
供稿:網友

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還提供了其他類來扶助線程操作,這里就不一一羅列。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
91精品免费久久久久久久久| 国产一区二区三区在线播放免费观看| 日韩高清不卡av| 日本高清视频精品| 91亚洲国产成人久久精品网站| 日韩成人中文字幕在线观看| 亚洲成人xxx| 成人午夜小视频| 日韩免费在线免费观看| 久久久女人电视剧免费播放下载| 欧美亚洲国产视频小说| 欧美日韩高清在线观看| 国产精品国产三级国产aⅴ浪潮| 国产在线播放91| 成人免费xxxxx在线观看| 97精品一区二区三区| 久久亚洲精品中文字幕冲田杏梨| 欧美日韩国产激情| 国产综合久久久久久| 国模精品一区二区三区色天香| 国产精品一区二区久久国产| 久久久久久久久爱| 久久久99久久精品女同性| 久久99久久久久久久噜噜| 亚洲美女视频网| 91av在线免费观看| 色噜噜狠狠色综合网图区| 亚洲性视频网站| 午夜精品在线观看| 亚洲va久久久噜噜噜久久天堂| 国产91精品青草社区| 亚洲精品久久久久久下一站| 中文字幕国产日韩| 亚洲桃花岛网站| 尤物yw午夜国产精品视频| 欧美视频裸体精品| www.午夜精品| 国产在线精品成人一区二区三区| 免费av在线一区| 中文字幕欧美精品在线| 久久91精品国产91久久久| 91在线观看免费高清完整版在线观看| 亚洲香蕉成视频在线观看| 欧美日韩国产精品一区| 国产精品中文字幕在线观看| 一个人www欧美| 国产精品∨欧美精品v日韩精品| 欧美激情在线有限公司| 亚洲激情视频在线观看| 日韩小视频网址| 69国产精品成人在线播放| 欧美一级视频一区二区| 96pao国产成视频永久免费| 亚洲国产毛片完整版| 国产一区二区三区高清在线观看| 日韩成人性视频| 亚洲高清久久久久久| 成人网在线视频| 色在人av网站天堂精品| 国产精品网站视频| 日本人成精品视频在线| yw.139尤物在线精品视频| 亚洲精选在线观看| 午夜美女久久久久爽久久| 亚洲精品国产精品久久清纯直播| 国产欧美韩国高清| 亚洲色图在线观看| 成人高清视频观看www| 夜夜嗨av色综合久久久综合网| 色综合久久88| 国产精品免费一区二区三区都可以| 岛国av午夜精品| 日韩亚洲欧美中文高清在线| 一区二区福利视频| 91av在线免费观看| 色偷偷综合社区| 亚洲欧美日韩国产中文专区| 成人精品久久久| 国产日韩在线视频| 日韩成人在线视频观看| 日韩av不卡电影| 亚洲女同精品视频| 精品性高朝久久久久久久| 国产午夜精品免费一区二区三区| 国产精品亚洲美女av网站| 韩剧1988免费观看全集| 精品亚洲一区二区| 日韩中文字幕不卡视频| 欧美国产精品人人做人人爱| 亚洲欧洲日韩国产| 欧美激情精品久久久| 青青a在线精品免费观看| 国产一区深夜福利| 国产成人在线播放| 欧美久久精品午夜青青大伊人| 色中色综合影院手机版在线观看| 狠狠躁夜夜躁人人爽天天天天97| 欧美久久精品一级黑人c片| 亚洲精品在线不卡| 粗暴蹂躏中文一区二区三区| 久久99精品视频一区97| 亚洲精品一区av在线播放| 久久久久久国产三级电影| 日韩精品在线影院| 91精品久久久久久| 日韩中文在线中文网在线观看| 久久精品国产视频| 亚洲最大的网站| 国产欧美日韩精品在线观看| 欧美日韩国产麻豆| 亚洲国产成人爱av在线播放| 亚洲免费视频网站| 亚洲第一综合天堂另类专| 福利视频第一区| 日韩国产在线看| 中文字幕精品www乱入免费视频| 日韩乱码在线视频| 97视频人免费观看| 久久精品青青大伊人av| 欧美国产亚洲精品久久久8v| 中文字幕亚洲国产| 日本a级片电影一区二区| 97国产精品视频人人做人人爱| 日韩免费黄色av| 97久久久久久| 亚洲精品乱码久久久久久按摩观| 日韩亚洲在线观看| 欧美激情精品久久久久久大尺度| 日韩av在线播放资源| 欧美成人一区二区三区电影| 日本久久久久亚洲中字幕| 国产成人精品999| 欧美野外猛男的大粗鳮| 国产福利精品在线| 45www国产精品网站| 久久久久日韩精品久久久男男| 草民午夜欧美限制a级福利片| 日韩一区二区三区xxxx| 成人国产亚洲精品a区天堂华泰| 日韩中文字幕视频| 国产精品一区久久| 国产视频亚洲视频| 欧洲午夜精品久久久| 岛国av午夜精品| 国产国产精品人在线视| 欧美性xxxxx| 日韩在线免费av| 91久久嫩草影院一区二区| 国产精品视频自拍| 午夜精品福利视频| 日韩中文字幕在线播放| 欧美成人在线免费| 色综合亚洲精品激情狠狠| 日韩av电影中文字幕| 欧美wwwwww| 欧美精品久久一区二区| 亚洲男人天堂九九视频| 国产精品第七影院| 亚洲男人天堂手机在线| 国产视频综合在线| 欧美夫妻性生活xx| 亚洲欧洲一区二区三区久久| 91精品视频在线| 国产亚洲精品久久久|