中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C#中線程和任務實例分析

發布時間:2022-03-19 09:42:07 來源:億速云 閱讀:154 作者:iii 欄目:開發技術

這篇文章主要介紹“C#中線程和任務實例分析”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“C#中線程和任務實例分析”文章能幫助大家解決問題。

    線程

    線程:對于所有需要等待的操作,例如移動文件,數據庫和網絡訪問都需要一定的時間,此時就可以啟動一個新的線程,同時完成其他任務。一個進程的多個線程可以同時運行在不同的CPU上或多核CPU的不同內核上。

    一個應用程序啟動時,會啟動一個進程(應用程序的載體),然后進程會啟動多個線程。

    一,使用Thread類啟動線程和數據傳輸

    使用Thread類可以創建和控制線程,Thread構造函數是一個無參無返回值的委托類型。

    1??對Thread傳入一個無參無返回類型的方法-ThreadStart。

        public delegate void ThreadStart();

    實例:

            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");
            }

    C#中線程和任務實例分析

    2??對Thread傳入一個匿名方法(或lambda表達式)。用于傳入的方法代碼簡單的情況

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

    C#中線程和任務實例分析

    3??對Thread傳入一個無返回值有參方法-ParameterizedThreadStart,該參數只能是object類型且只能有一個參數。

        public delegate void ParameterizedThreadStart(object? obj);

    實例:

            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");
            }

    C#中線程和任務實例分析

    注意:使用as進行強制類型轉換 成功會正確輸出,失敗會輸出null。

    以上數據傳輸的方法都是基于靜態變量進行傳輸的,但是定義過多靜態變量會導致多個線程訪問同一個靜態變量,造成資源沖突。

    靜態變量雖然方便訪問,但是靜態的一般都是公共的,容易混亂。

    4??對Thread傳入一個無返回值多個參數的方法(定義一個結構體),但是不能用as強制轉換。

            public struct data
            {
                public string message;
                public int age;
            }
            static void download(object o)
            {
                data str = (data)o;//強制類型轉換
                Console.WriteLine("信息:" + str.message);
                Console.WriteLine("年紀:" + 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");
            }

    由于結構體是值類型,不能為null,因此不能用as進行強制類型轉換。

    5??通過自定義類傳遞數據(即將通過線程調用一個類的成員方法)

    先創建一個download類:

        class downLoad
        {
            public string URL { get; private set; }
            public string Message { get; private set; }
            //構造函數
            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();
            }

    ????知識點拓展1-前臺線程與后臺線程:

    應用程序的進程需要等待所有前臺線程完成其任務后才會結束。而后臺線程在應用程序關閉后會自動關閉,即使后臺線程還沒有執行完畢。在默認情況下,用Thread類創建的線程是前臺線程,線程池中的線程是后臺線程。在Thread類創建線程的時候,可以設置IsBackground屬性,表示它是否是一個后臺線程。

    ????知識點拓展2-線程的優先級

    線程有操作系統調度,一個CPU同一時間只能做一件事(運行一個線程中的計算任務),當有很多線程需要CPU執行時,線程調度器會根據線程的優先級去判斷先去執行哪個線程,如果優先級相同,就使用一個循環調度規則,逐個執行每個線程。

    在Thread類中,可以設置Priority屬性,以影響線程的基本優先級,Priority屬性一個ThreadPriority枚舉定義的一個值,定義級別有Highest,AboveNormal,Normal,BelowNormal,和Lowest。

    因此對于重要的線程任務,可以將線程優先級設置高一點,使其可以盡快執行完畢。

    如果需要等待線程執行結果在執行后面的代碼,可以調用Thread對象的join方法,即將該線程加入進來,并停止當前線程,直至加入的線程執行完畢。

    二,線程池ThreadPool類

    由于線程的創建需要時間,如果有不同的小任務要完成,就可以事先創建多個線程。系統有一個ThreadPool類來管理線程,這個類會在需要線程的時候增加線程數,不需要時候減少。池中最大線程數是可配置的。在雙核CPU中,默認設置為1023個工作線程和1000個IO線程,如果需要更多線程(超過了線程池的最大數量),最新的任務就需要排隊等待。

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

            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);
            }

    C#中線程和任務實例分析

    需要注意的是:

    線程池中所有線程都是后臺線程,如果進程中所有的前臺線程都結束了,所有的后臺線程也會跟著結束。不能把入池的后臺線程改為前臺線程。不能給入池的線程設置優先級或名稱。入池的線程只能是用于時間較短的任務。如果線程要一直運行,就應用Thread類創建一個線程。

    任務

    任務表示應完成某個單元的工作,這個工作可以在單獨的線程中運行,也可以同步方式啟動一個任務。任務在后臺使用ThreadPool進行管理的,也就是說任務啟動的也是后臺線程。

    一,創建并啟動任務

    啟動任務的兩種方式:

            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);
            }

    C#中線程和任務實例分析

    需要注意的是:使用TaskFactory創建任務,傳入的方法為無參的。

    二,連續任務

    如果一個任務t1的執行是依賴于另一個任務t2,那么就需要在t2執行完畢后才開始執行t1。(例如:迅雷下載完成后彈出界面提示)這時候我們可以使用連續任務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("下載完成!");
            }

    C#中線程和任務實例分析

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

    三,資源沖突問題

    在多線程中如果多個線程同時訪問同一資源,就會產生資源沖突的問題。這時候需要用lock對程序進行加鎖。

    ????什么是資源沖突?

        class state
        {
            public int num = 5;
            public void checknum()
            {
                if (num==5)
                {
                    num++;
                    Console.WriteLine("num的值:" + num + "當前線程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();
                }
            }

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

    C#中線程和任務實例分析

    ????對多個線程訪問的對象進行加鎖

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

    C#中線程和任務實例分析

    關于“C#中線程和任務實例分析”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    建宁县| 舟曲县| 清水县| 昭平县| 嘉禾县| 兴山县| 贵南县| 东源县| 泽库县| 民权县| 习水县| 崇文区| 泰州市| 泸西县| 房产| 祁东县| 湄潭县| 福贡县| 手机| 门源| 威远县| 安塞县| 永仁县| 福贡县| 上饶县| 北票市| 南投市| 桑植县| 盘山县| 罗甸县| 永城市| 沧源| 建始县| 额济纳旗| 合水县| 石首市| 武强县| 襄城县| 博湖县| 河津市| 赣榆县|