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

C#中Thread(線程)和Task(任務(wù))實(shí)例詳解

 更新時(shí)間:2022年03月19日 08:39:11   作者:唯有自己強(qiáng)大  
.NET Framework在System.Threading命名空間中具有與線程相關(guān)的類,線程是一小組可執(zhí)行指令,這篇文章主要給大家介紹了關(guān)于C#中Thread(線程)和Task(任務(wù))的相關(guān)資料,需要的朋友可以參考下

線程

線程:對(duì)于所有需要等待的操作,例如移動(dòng)文件,數(shù)據(jù)庫(kù)和網(wǎng)絡(luò)訪問(wèn)都需要一定的時(shí)間,此時(shí)就可以啟動(dòng)一個(gè)新的線程,同時(shí)完成其他任務(wù)。一個(gè)進(jìn)程的多個(gè)線程可以同時(shí)運(yùn)行在不同的CPU上或多核CPU的不同內(nèi)核上。

一個(gè)應(yīng)用程序啟動(dòng)時(shí),會(huì)啟動(dòng)一個(gè)進(jìn)程(應(yīng)用程序的載體),然后進(jìn)程會(huì)啟動(dòng)多個(gè)線程。

一,使用Thread類啟動(dòng)線程和數(shù)據(jù)傳輸

使用Thread類可以創(chuàng)建和控制線程,Thread構(gòu)造函數(shù)是一個(gè)無(wú)參無(wú)返回值的委托類型。

1??對(duì)Thread傳入一個(gè)無(wú)參無(wú)返回類型的方法-ThreadStart。

    public delegate void ThreadStart();

實(shí)例:

        static  void test()
        {
            Console.WriteLine("test is start");
            Console.WriteLine("test is running");
            Thread.Sleep(3000);
            Console.WriteLine("test is completed");
        }

        static void Main(string[] args)
        {
            Thread th = new Thread(test);
            th.Start();
            Console.WriteLine("main is completed");
        }

2??對(duì)Thread傳入一個(gè)匿名方法(或lambda表達(dá)式)。用于傳入的方法代碼簡(jiǎn)單的情況

        static void Main(string[] args)
        {
            //lambad表達(dá)式
            Thread th = new Thread(()=> {
                Console.WriteLine("子線程1-ID:" + Thread.CurrentThread.ManagedThreadId);
            });
            th.Start();
            //匿名方法
            Thread th2 = new Thread(delegate ()
            {
                Console.WriteLine("子線程2-ID:" + Thread.CurrentThread.ManagedThreadId);
            });
            th2.Start();
            Console.WriteLine("main is completed");
        }

3??對(duì)Thread傳入一個(gè)無(wú)返回值有參方法-ParameterizedThreadStart,該參數(shù)只能是object類型且只能有一個(gè)參數(shù)。

    public delegate void ParameterizedThreadStart(object? obj);

實(shí)例:

        static void download(object o)
        {
            string str = o as string;
            Console.WriteLine("地址:" + str);
        }
        static void Main(string[] args)
        {
            Thread th = new Thread(download);
            th.Start("http://baidu.com");
            Console.WriteLine("main is completed");
        }

注意:使用as進(jìn)行強(qiáng)制類型轉(zhuǎn)換 成功會(huì)正確輸出,失敗會(huì)輸出null。

以上數(shù)據(jù)傳輸?shù)姆椒ǘ际腔陟o態(tài)變量進(jìn)行傳輸?shù)?,但是定義過(guò)多靜態(tài)變量會(huì)導(dǎo)致多個(gè)線程訪問(wèn)同一個(gè)靜態(tài)變量,造成資源沖突。

靜態(tài)變量雖然方便訪問(wèn),但是靜態(tài)的一般都是公共的,容易混亂。

4??對(duì)Thread傳入一個(gè)無(wú)返回值多個(gè)參數(shù)的方法(定義一個(gè)結(jié)構(gòu)體),但是不能用as強(qiáng)制轉(zhuǎn)換。

        public struct data
        {
            public string message;
            public int age;
        }
        static void download(object o)
        {
            data str = (data)o;//強(qiáng)制類型轉(zhuǎn)換
            Console.WriteLine("信息:" + str.message);
            Console.WriteLine("年紀(jì):" + str.age);
        }
        static void Main(string[] args)
        {
            data da = new data();
            da.message = "sss";
            da.age = 3;
            Thread th = new Thread(download);
            th.Start(da);
            Console.WriteLine("main is completed");
        }

由于結(jié)構(gòu)體是值類型,不能為null,因此不能用as進(jìn)行強(qiáng)制類型轉(zhuǎn)換。

5??通過(guò)自定義類傳遞數(shù)據(jù)(即將通過(guò)線程調(diào)用一個(gè)類的成員方法)

先創(chuàng)建一個(gè)download類:

    class downLoad
    {
        public string URL { get; private set; }
        public string Message { get; private set; }
        //構(gòu)造函數(shù)
        public downLoad(string uRL, string message)
        {
            URL = uRL;
            Message = message;
        }
        //下載方法
        public void  load()
        {
            Console.WriteLine("從" + URL + "獲取信息:" + Message);
        }
    }

在主程序中將該類的成員方法傳入Thread中:

   static void Main(string[] args)
        {
            var download = new downLoad("www.baidu.com", "mp4");
            Thread th = new Thread(download.load);
            th.Start();
            Console.WriteLine("main is completed");
            Console.ReadKey();
        }

??知識(shí)點(diǎn)拓展1-前臺(tái)線程與后臺(tái)線程:

應(yīng)用程序的進(jìn)程需要等待所有前臺(tái)線程完成其任務(wù)后才會(huì)結(jié)束。而后臺(tái)線程在應(yīng)用程序關(guān)閉后會(huì)自動(dòng)關(guān)閉,即使后臺(tái)線程還沒(méi)有執(zhí)行完畢。在默認(rèn)情況下,用Thread類創(chuàng)建的線程是前臺(tái)線程,線程池中的線程是后臺(tái)線程。在Thread類創(chuàng)建線程的時(shí)候,可以設(shè)置IsBackground屬性,表示它是否是一個(gè)后臺(tái)線程。

??知識(shí)點(diǎn)拓展2-線程的優(yōu)先級(jí)

線程有操作系統(tǒng)調(diào)度,一個(gè)CPU同一時(shí)間只能做一件事(運(yùn)行一個(gè)線程中的計(jì)算任務(wù)),當(dāng)有很多線程需要CPU執(zhí)行時(shí),線程調(diào)度器會(huì)根據(jù)線程的優(yōu)先級(jí)去判斷先去執(zhí)行哪個(gè)線程,如果優(yōu)先級(jí)相同,就使用一個(gè)循環(huán)調(diào)度規(guī)則,逐個(gè)執(zhí)行每個(gè)線程。

在Thread類中,可以設(shè)置Priority屬性,以影響線程的基本優(yōu)先級(jí),Priority屬性一個(gè)ThreadPriority枚舉定義的一個(gè)值,定義級(jí)別有Highest,AboveNormal,Normal,BelowNormal,和Lowest。

因此對(duì)于重要的線程任務(wù),可以將線程優(yōu)先級(jí)設(shè)置高一點(diǎn),使其可以盡快執(zhí)行完畢。

如果需要等待線程執(zhí)行結(jié)果在執(zhí)行后面的代碼,可以調(diào)用Thread對(duì)象的join方法,即將該線程加入進(jìn)來(lái),并停止當(dāng)前線程,直至加入的線程執(zhí)行完畢。

二,線程池ThreadPool類

由于線程的創(chuàng)建需要時(shí)間,如果有不同的小任務(wù)要完成,就可以事先創(chuàng)建多個(gè)線程。系統(tǒng)有一個(gè)ThreadPool類來(lái)管理線程,這個(gè)類會(huì)在需要線程的時(shí)候增加線程數(shù),不需要時(shí)候減少。池中最大線程數(shù)是可配置的。在雙核CPU中,默認(rèn)設(shè)置為1023個(gè)工作線程和1000個(gè)IO線程,如果需要更多線程(超過(guò)了線程池的最大數(shù)量),最新的任務(wù)就需要排隊(duì)等待。

使用線程池,即調(diào)用ThreadPool.QueueUserWorkItem方法,該方法需要傳入一個(gè)WaitCallBack類型的委托(即傳入帶一個(gè)object參數(shù)的方法)。然后ThreadPool會(huì)在池中找一個(gè)空閑的線程去執(zhí)行傳入的方法。

        static void Main(string[] args)
        {
            for (int i = 0; i < 10; i++)
            {
                ThreadPool.QueueUserWorkItem(work);              
            }
            Thread.Sleep(10000);
        }
        static void work(object state)
        {
            Console.WriteLine("線程id" + Thread.CurrentThread.ManagedThreadId);
        }

需要注意的是:

線程池中所有線程都是后臺(tái)線程,如果進(jìn)程中所有的前臺(tái)線程都結(jié)束了,所有的后臺(tái)線程也會(huì)跟著結(jié)束。不能把入池的后臺(tái)線程改為前臺(tái)線程。不能給入池的線程設(shè)置優(yōu)先級(jí)或名稱。入池的線程只能是用于時(shí)間較短的任務(wù)。如果線程要一直運(yùn)行,就應(yīng)用Thread類創(chuàng)建一個(gè)線程。

任務(wù)

任務(wù)表示應(yīng)完成某個(gè)單元的工作,這個(gè)工作可以在單獨(dú)的線程中運(yùn)行,也可以同步方式啟動(dòng)一個(gè)任務(wù)。任務(wù)在后臺(tái)使用ThreadPool進(jìn)行管理的,也就是說(shuō)任務(wù)啟動(dòng)的也是后臺(tái)線程。

一,創(chuàng)建并啟動(dòng)任務(wù)

啟動(dòng)任務(wù)的兩種方式:

        static void Main(string[] args)
        {
            //第一種:使用TaskFactory
            TaskFactory tf = new TaskFactory();
            tf.StartNew(work);
            //第二種:使用Task
            Task t = new Task(work);
            t.Start();
            Console.WriteLine("main is completed");
        }
        static void work()
        {
            Console.WriteLine("線程id" + Thread.CurrentThread.ManagedThreadId);
        }

需要注意的是:使用TaskFactory創(chuàng)建任務(wù),傳入的方法為無(wú)參的。

二,連續(xù)任務(wù)

如果一個(gè)任務(wù)t1的執(zhí)行是依賴于另一個(gè)任務(wù)t2,那么就需要在t2執(zhí)行完畢后才開(kāi)始執(zhí)行t1。(例如:迅雷下載完成后彈出界面提示)這時(shí)候我們可以使用連續(xù)任務(wù)ContinueWith。

        static void Main(string[] args)
        {
            Task t1 = new Task(download);
            Task t2 = t1.ContinueWith(show);
            t1.Start();
            Thread.Sleep(2000);
        }
        static void download()
        {
            Console.WriteLine("正在下載中。。。。");
            Thread.Sleep(1000);
        }
        static void show(Task t)
        {
            Console.WriteLine("下載完成!");
        }

需要注意的是:傳入t2的方法的參數(shù)需為Task類型。

三,資源沖突問(wèn)題

在多線程中如果多個(gè)線程同時(shí)訪問(wèn)同一資源,就會(huì)產(chǎn)生資源沖突的問(wèn)題。這時(shí)候需要用lock對(duì)程序進(jìn)行加鎖。

??什么是資源沖突?

    class state
    {
        public int num = 5;
        public void checknum()
        {
            if (num==5)
            {
                num++;
                Console.WriteLine("num的值:" + num + "當(dāng)前線程id:" + Thread.CurrentThread.ManagedThreadId); 
            }
            num =5;
        }
    }
  static void Main(string[] args)
        {
            state st = new state();
            for (int i = 0; i < 10; i++)
            {
                Thread th = new Thread(st.checknum);
                th.Start();
            }
        }

在主程序使用多線程調(diào)用state類的check方法,可以看到num=5和num=6造成資源沖突了。

??對(duì)多個(gè)線程訪問(wèn)的對(duì)象進(jìn)行加鎖

        object _lock = new object();
        public int num = 5;
        public void checknum()
        {
            lock(_lock)
            {
            if (num==5)
            {
                num++;
                Console.WriteLine("num的值:" + num + "當(dāng)前線程id:" + Thread.CurrentThread.ManagedThreadId); 
            }
            num =5;
            }
        }

 總結(jié)

到此這篇關(guān)于C#中Thread(線程)和Task(任務(wù))的文章就介紹到這了,更多相關(guān)C# 線程和任務(wù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C# 設(shè)計(jì)模式系列教程-抽象工廠模式

    C# 設(shè)計(jì)模式系列教程-抽象工廠模式

    抽象工廠模式為創(chuàng)建一組相關(guān)或相互依賴的對(duì)象提供一個(gè)接口,而且無(wú)需指定他們的具體類。
    2016-06-06
  • C# 添加Word文本和圖片超鏈接的方法

    C# 添加Word文本和圖片超鏈接的方法

    本文給大家介紹如何用C#編程語(yǔ)言對(duì)Word文檔中的文本和圖片進(jìn)行超鏈接設(shè)置。感興趣的朋友一起看看吧
    2017-10-10
  • Unity中的靜態(tài)批處理和動(dòng)態(tài)批處理操作

    Unity中的靜態(tài)批處理和動(dòng)態(tài)批處理操作

    這篇文章主要介紹了Unity中的靜態(tài)批處理和動(dòng)態(tài)批處理操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-04-04
  • C#延時(shí)函數(shù)的使用說(shuō)明

    C#延時(shí)函數(shù)的使用說(shuō)明

    這篇文章主要介紹了C#延時(shí)函數(shù)的使用說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • WPF利用ScottPlot實(shí)現(xiàn)動(dòng)態(tài)繪制圖像

    WPF利用ScottPlot實(shí)現(xiàn)動(dòng)態(tài)繪制圖像

    ScottPlot是基于.Net的一款開(kāi)源免費(fèi)的交互式可視化庫(kù),支持Winform和WPF等UI框架,本文主要為大家詳細(xì)介紹了如何WPF如何使用ScottPlot實(shí)現(xiàn)動(dòng)態(tài)繪制圖像,需要的可以參考下
    2023-12-12
  • Unity接入百度AI實(shí)現(xiàn)果蔬識(shí)別

    Unity接入百度AI實(shí)現(xiàn)果蔬識(shí)別

    本文將介紹如何利用Unity接入百度AI從而實(shí)現(xiàn)果蔬識(shí)別,可以做到識(shí)別近千種水果和蔬菜的名稱,可自定義返回識(shí)別結(jié)果數(shù)。感興趣的小伙伴可以了解一下
    2022-02-02
  • C#實(shí)現(xiàn)讀取指定盤符硬盤序列號(hào)的方法

    C#實(shí)現(xiàn)讀取指定盤符硬盤序列號(hào)的方法

    這篇文章主要介紹了C#實(shí)現(xiàn)讀取指定盤符硬盤序列號(hào)的方法,涉及C#針對(duì)硬件屬性的相關(guān)操作技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2016-08-08
  • C#通過(guò)屬性名字符串獲取、設(shè)置對(duì)象屬性值操作示例

    C#通過(guò)屬性名字符串獲取、設(shè)置對(duì)象屬性值操作示例

    這篇文章主要介紹了C#通過(guò)屬性名字符串獲取、設(shè)置對(duì)象屬性值操作,結(jié)合實(shí)例形式總結(jié)分析了C#通過(guò)反射獲取對(duì)象屬性值并設(shè)置屬性值,獲取對(duì)象的所有屬性名稱及類型等相關(guān)操作技巧,需要的朋友可以參考下
    2020-03-03
  • 關(guān)于C#基礎(chǔ)知識(shí)回顧--反射(二)

    關(guān)于C#基礎(chǔ)知識(shí)回顧--反射(二)

    其實(shí)說(shuō)白了,反射就是能知道我們未知類型的類型信息這么一個(gè)東西.沒(méi)什么神秘可講!反射的核心是System.Type。System.Type包含了很多屬性和方法,使用這些屬性和方法可以在運(yùn)行時(shí)得到類型信息
    2013-07-07
  • C#實(shí)現(xiàn)優(yōu)先隊(duì)列和堆排序

    C#實(shí)現(xiàn)優(yōu)先隊(duì)列和堆排序

    本文詳細(xì)講解了C#實(shí)現(xiàn)優(yōu)先隊(duì)列和堆排序的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-04-04

最新評(píng)論