欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

c#線(xiàn)程Thread示例

 更新時(shí)間:2014年05月01日 09:05:40   作者:  
這篇文章主要介紹了c#線(xiàn)程Thread示例,需要的朋友可以參考下

C#是一門(mén)支持多線(xiàn)程的語(yǔ)言,因此線(xiàn)程的使用也是比較常見(jiàn)的。由于線(xiàn)程的知識(shí)在Win32編程的時(shí)候已經(jīng)說(shuō)得過(guò)多,所以在.Net中很少介紹這部分(可能.Net不覺(jué)得這部分是它所特有的)。

那么線(xiàn)程相關(guān)的問(wèn)題大致有如下四類(lèi)(這篇文章只討論單線(xiàn)程、單線(xiàn)程與UI線(xiàn)程這兩方面的問(wèn)題)。
問(wèn)題一,線(xiàn)程的基本操作,例如:暫停、繼續(xù)、停止等;
問(wèn)題二,如何向線(xiàn)程傳遞參數(shù)或者從中得到其返回值;
問(wèn)題三,如何使線(xiàn)程所占用的CPU不要老是百分之百;
最后一個(gè),也是問(wèn)題最多的,就是如何在子線(xiàn)程來(lái)控制UI中的控件,換句話(huà)說(shuō),就是在線(xiàn)程中控制窗體某些控件的顯示。

對(duì)于問(wèn)題一,我不建議使用Thread類(lèi)提供的Suspend、Resume以及Abort這三個(gè)方法,前兩個(gè)有問(wèn)題,好像在VS05已經(jīng)屏蔽這兩個(gè)方法;對(duì)于Abort來(lái)說(shuō),除了資源沒(méi)有得到及時(shí)釋放外,有時(shí)候會(huì)出現(xiàn)異常。如何做呢,通過(guò)設(shè)置開(kāi)關(guān)變量來(lái)完成。

對(duì)于問(wèn)題二,我不建議使用靜態(tài)成員來(lái)完成,僅僅為了線(xiàn)程而破壞類(lèi)的封裝有些得不償失。那如何做呢,通過(guò)創(chuàng)建單獨(dú)的線(xiàn)程類(lèi)來(lái)完成。

對(duì)于問(wèn)題三來(lái)說(shuō),造成這個(gè)原因是由于線(xiàn)程中進(jìn)行不間斷的循環(huán)操作,從而使CPU完全被子線(xiàn)程占有。那么處理此類(lèi)問(wèn)題,其實(shí)很簡(jiǎn)單,在適當(dāng)?shù)奈恢谜{(diào)用Thread.Sleep(20)來(lái)釋放所占有CPU資源,不要小看這20毫秒的睡眠,它的作用可是巨大的,可以使其他線(xiàn)程得到CPU資源,從而使你的CPU使用效率降下來(lái)。

看完前面的三個(gè)問(wèn)題的解釋?zhuān)瑢?duì)于如何做似乎沒(méi)有給出一個(gè)明確的答案,為了更好地說(shuō)明如何解決這三個(gè)問(wèn)題,我用一個(gè)比較完整的例子展現(xiàn)給大家,代碼如下。

復(fù)制代碼 代碼如下:

//--------------------------- 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
}
}

那么對(duì)于調(diào)用呢,就非常簡(jiǎn)單了,如下:
// 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();

在回過(guò)頭來(lái)看看前面所說(shuō)的三個(gè)問(wèn)題。
對(duì)于問(wèn)題一來(lái)說(shuō),首先需要局部成員的支持,那么
private Mutex mUnique = new Mutex();

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

光看成員名稱(chēng),估計(jì)大家都已經(jīng)猜出其代表的意思。接下來(lái)需要修改線(xiàn)程入口函數(shù),要是這些開(kāi)關(guān)變量能發(fā)揮作用,那么看看SubThread這個(gè)函數(shù)。
/// <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 );
}

函數(shù)比較簡(jiǎn)單,不到十句,可能對(duì)于“blnIsStopped == false”這個(gè)判斷來(lái)說(shuō),大家還比較好理解,這是一個(gè)普通的判斷,如果當(dāng)前Stop開(kāi)關(guān)打開(kāi)了,就停止循環(huán);否則一直循環(huán)。
大家比較迷惑的可能是如下這兩句:
mUnique.WaitOne();
mUnique.ReleaseMutex();
這兩句的目的是為了使線(xiàn)程在Suspend操作的時(shí)候能發(fā)揮效果,為了解釋這兩句,需要結(jié)合Suspend和Resume這兩個(gè)方法,它倆的代碼如下。
/// <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();
}
}


為了更好地說(shuō)明,還需要先簡(jiǎn)單說(shuō)說(shuō)Mutex類(lèi)型。對(duì)于此類(lèi)型對(duì)象,當(dāng)調(diào)用對(duì)象的WaitOne之后,如果此時(shí)沒(méi)有其他線(xiàn)程對(duì)它使用的時(shí)候,就立刻獲得信號(hào)量,繼續(xù)執(zhí)行代碼;當(dāng)再調(diào)用ReleaseMutex之前,如果再調(diào)用對(duì)象的WaitOne方法,就會(huì)一直等待,直到獲得信號(hào)量的調(diào)用ReleaseMutex來(lái)進(jìn)行釋放。這就好比衛(wèi)生間的使用,如果沒(méi)有人使用則可以直接使用,否則只有等待。
明白了這一點(diǎn)后,再來(lái)解釋這兩句所能出現(xiàn)的現(xiàn)象。
復(fù)制代碼 代碼如下:

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


當(dāng)在線(xiàn)程函數(shù)中,執(zhí)行到“mUnique.WaitOne();”這一句的時(shí)候,如果此時(shí)外界沒(méi)有發(fā)送Suspend消息,也就是信號(hào)量沒(méi)有被占用,那么這一句可以立刻返回。那么為什么要緊接著釋放呢,因?yàn)椴荒芸傉贾盘?hào)量,立即釋放信號(hào)量是避免在發(fā)送Suspend命令的時(shí)候出現(xiàn)等待;如果此時(shí)外界已經(jīng)發(fā)送了Suspend消息,也就是說(shuō)信號(hào)量已經(jīng)被占用,此時(shí)“mUnique.WaitOne();”不能立刻返回,需要等到信號(hào)量被釋放才能繼續(xù)進(jìn)行,也就是需要調(diào)用Resume的時(shí)候,“mUnique.WaitOne();”才能獲得信號(hào)量進(jìn)行繼續(xù)執(zhí)行。這樣才能達(dá)到真正意義上的Suspend和Resume。

至于線(xiàn)程的Start和Stop來(lái)說(shuō),相對(duì)比較簡(jiǎn)單,這里我就不多說(shuō)了。

現(xiàn)在再來(lái)分析一下問(wèn)題二,其實(shí)例子比較明顯,是通過(guò)構(gòu)造函數(shù)和屬性來(lái)完成參數(shù)和返回值,這一點(diǎn)我也不多說(shuō)了。如果線(xiàn)程參數(shù)比較多的話(huà),可以考慮屬性來(lái)完成,類(lèi)似于返回值。

問(wèn)題三,我就更不用多說(shuō)了。有人說(shuō)了,如果子線(xiàn)程中的循環(huán)不能睡眠怎么辦,因?yàn)樗叩脑?huà),有時(shí)會(huì)造成數(shù)據(jù)丟失,這方面的可以借鑒前面Suspend的做法,如果更復(fù)雜,則牽扯到多線(xiàn)程的同步問(wèn)題,這部分我會(huì)稍后單獨(dú)寫(xiě)一篇文章。

前三個(gè)問(wèn)題解決了,該說(shuō)說(shuō)最常見(jiàn)的問(wèn)題,如何在子線(xiàn)程中控制窗體控件。這也是寫(xiě)線(xiàn)程方面程序經(jīng)常遇到的。

首先說(shuō)說(shuō),為什么不能直接在子線(xiàn)程中操縱UI呢。原因在于子線(xiàn)程和UI線(xiàn)程屬于不同的上下文,換句比較通俗的話(huà)說(shuō),就好比兩個(gè)人在不同的房間里一樣,那么要你直接操作另一個(gè)房間里的東西,恐怕不行罷,那么對(duì)于子線(xiàn)程來(lái)說(shuō)也一樣,不能直接操作UI線(xiàn)程中的對(duì)象。

那么如何在子線(xiàn)程中操縱UI線(xiàn)程中的對(duì)象呢,.Net提供了Invoke和BeginInvoke這兩種方法。簡(jiǎn)單地說(shuō),就是子線(xiàn)程發(fā)消息讓UI線(xiàn)程來(lái)完成相應(yīng)的操作。

這兩個(gè)方法有什么區(qū)別,這在我以前的文章已經(jīng)說(shuō)過(guò)了,Invoke需要等到所調(diào)函數(shù)的返回,而B(niǎo)eginInvoke則不需要。

用這兩個(gè)方法需要注意的,有如下三點(diǎn):
第一個(gè)是由于Invoke和BeginInvoke屬于Control類(lèi)型的成員方法,因此調(diào)用的時(shí)候,需要得到Control類(lèi)型的對(duì)象才能觸發(fā),也就是說(shuō)你要觸發(fā)窗體做什么操作或者窗體上某個(gè)控件做什么操作,需要把窗體對(duì)象或者控件對(duì)象傳遞到線(xiàn)程中。

第二個(gè),對(duì)于Invoke和BeginInvoke接受的參數(shù)屬于一個(gè)delegate類(lèi)型,我在以前的文章中使用的是MethodInvoker,這是.Net自帶的一個(gè)delegate類(lèi)型,而并不意味著在使用Invoke或者BeginInvoke的時(shí)候只能用它。參看我給的第二篇文章(《如何彈出一個(gè)模式窗口來(lái)顯示進(jìn)度條》),會(huì)有很多不同的delegate定義。

最后一個(gè),使用Invoke和BeginInvoke有個(gè)需要注意的,就是當(dāng)子線(xiàn)程在Form_Load開(kāi)啟的時(shí)候,會(huì)遇到異常,這是因?yàn)橛|發(fā)Invoke的對(duì)象還沒(méi)有完全初始化完畢。處理此類(lèi)問(wèn)題,在開(kāi)啟線(xiàn)程之前顯式的調(diào)用“this.Show();”,來(lái)使窗體顯示在線(xiàn)程開(kāi)啟之前。如果此時(shí)只是開(kāi)啟線(xiàn)程來(lái)初始化顯示數(shù)據(jù),那我建議你不要使用子線(xiàn)程,用Splash窗體的效果可能更好。
線(xiàn)程的四個(gè)相關(guān)問(wèn)題已經(jīng)說(shuō)完了,這篇文章只說(shuō)了單線(xiàn)程,以及單線(xiàn)程與UI線(xiàn)程交互的問(wèn)題。其中涉及到的方法不一定是唯一的,因?yàn)?Net還提供了其他類(lèi)來(lái)扶助線(xiàn)程操作,這里就不一一羅列。

相關(guān)文章

  • Unity UGUI教程之實(shí)現(xiàn)滑頁(yè)效果

    Unity UGUI教程之實(shí)現(xiàn)滑頁(yè)效果

    使用UGUI提供的ScrollRect和ScrollBar組件實(shí)現(xiàn)基本滑動(dòng)以及自己控制每次移動(dòng)一頁(yè)來(lái)達(dá)到滑頁(yè)的效果。具體實(shí)現(xiàn)思路請(qǐng)參考下本教程
    2016-04-04
  • C#同步網(wǎng)絡(luò)時(shí)間的方法實(shí)例詳解

    C#同步網(wǎng)絡(luò)時(shí)間的方法實(shí)例詳解

    這篇文章主要介紹了C#同步網(wǎng)絡(luò)時(shí)間的方法,以實(shí)例形式較為詳細(xì)的分析了C#獲取網(wǎng)絡(luò)時(shí)間與同步本機(jī)系統(tǒng)時(shí)間的相關(guān)技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2015-05-05
  • Unity中C#和Java的相互調(diào)用實(shí)例代碼

    Unity中C#和Java的相互調(diào)用實(shí)例代碼

    在unity中接入sdk或者定制一些功能時(shí),需要調(diào)用系統(tǒng)接口。安卓手機(jī)實(shí)際操作中,也就是Unity與android相互調(diào)用。我們?cè)赨nity中使用c#,android中使用java。
    2018-02-02
  • C#實(shí)現(xiàn)彈窗提示輸入密碼

    C#實(shí)現(xiàn)彈窗提示輸入密碼

    這篇文章主要為大家詳細(xì)介紹了C#實(shí)現(xiàn)彈窗提示輸入密碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • C#中類(lèi)與結(jié)構(gòu)的區(qū)別實(shí)例分析

    C#中類(lèi)與結(jié)構(gòu)的區(qū)別實(shí)例分析

    這篇文章主要介紹了C#中類(lèi)與結(jié)構(gòu)的區(qū)別,類(lèi)與結(jié)構(gòu)是C#初學(xué)者比較輕易混淆的概念,本文加以實(shí)例說(shuō)明,需要的朋友可以參考下
    2014-08-08
  • C#遍歷文件夾及子目錄下所有圖片

    C#遍歷文件夾及子目錄下所有圖片

    這篇文章主要為大家詳細(xì)介紹了C# 遍歷文件夾及子目錄下所有圖片的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • Unity?UGUI的MaskableGraphic可遮罩圖形組件介紹使用

    Unity?UGUI的MaskableGraphic可遮罩圖形組件介紹使用

    這篇文章主要為大家介紹了Unity?UGUI的MaskableGraphic可遮罩圖形組件介紹使用,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • C#常見(jiàn)算法面試題小結(jié)

    C#常見(jiàn)算法面試題小結(jié)

    這篇文章主要介紹了C#常見(jiàn)算法面試題,包含了常見(jiàn)的排序、字符串操作、類(lèi)的操作等技巧,需要的朋友可以參考下
    2014-09-09
  • C#之Windows自帶打印功能的實(shí)現(xiàn)

    C#之Windows自帶打印功能的實(shí)現(xiàn)

    這篇文章主要介紹了C#之Windows自帶打印功能的實(shí)現(xiàn)方式,具有很好的價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • C#程序中類(lèi)數(shù)量對(duì)程序啟動(dòng)的影響詳解

    C#程序中類(lèi)數(shù)量對(duì)程序啟動(dòng)的影響詳解

    這篇文章主要給大家介紹了關(guān)于C#程序中類(lèi)數(shù)量對(duì)程序啟動(dòng)的影響的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-10-10

最新評(píng)論