多線程編程學習筆記-基礎(二)

来源:http://www.cnblogs.com/chillsrc/archive/2017/10/20/7699076.html
-Advertisement-
Play Games

接上文 多線程編程學習筆記-基礎(一) 五、終止線程 (Abort) 1.代碼如下 2.程式執行結果如下 從結果中,可以看出來,程式先啟動了子線程的列印數字方法,在運行了6秒之後,調用了abort方法,終止了子線程。但是這個abort是通過註入ThreadAbortException方法,從而使用線 ...


接上文 多線程編程學習筆記-基礎(一)

五、終止線程 (Abort)

1.代碼如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading; //引入線程 

namespace ThreadConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("開始");
            Thread t = new Thread(PrintNumberDely);

            //啟動線程
            t.Start();
            Thread.Sleep(TimeSpan.FromSeconds(6));

            //線程終止
            t.Abort();          

            Console.WriteLine("線程終止");
            Console.WriteLine("啟動新線程");
            t = new Thread(PrintNumber);
            t.Start();
            PrintNumber();
            Console.Read();          

        } 

        static void PrintNumber()
        {
            Console.WriteLine("第四個多線程程式開始。。。。Second:" + DateTime.Now.Second);
            for (int i = 0; i <10; i++)
            {
                Console.WriteLine(string.Format("{0}",i));
            }
        }

        /// <summary>
        /// 暫停2秒的方法
        /// </summary>
        static void PrintNumberDely()
        {
            Console.WriteLine("第一個多線程終止程式開始。。。。");
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine(string.Format("Second:{0} ==  {1}", DateTime.Now.Second, i));

                Thread.Sleep(TimeSpan.FromSeconds(2));            
          
            }
        }
    }
}

2.程式執行結果如下

 

 從結果中,可以看出來,程式先啟動了子線程的列印數字方法,在運行了6秒之後,調用了abort方法,終止了子線程。但是這個abort是通過註入ThreadAbortException方法,從而使用線程終止,這種方法非常危險,不建議使用。在子線程終止之後,主線程繼續運行。

 

六、檢測線程狀態(ThreadState)

1.代碼如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading; //引入線程

namespace ThreadConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("開始");
            Thread t = new Thread(PrintNumberStatus);
            Thread t2 = new Thread(DoNothing);
            //啟動線程
            t2.Start();
            t.Start();
            //顯示線程狀態
            for (int i = 0; i < 10; i++)
            {

                Thread.Sleep(TimeSpan.FromMilliseconds(300));
                Console.WriteLine(t.ThreadState.ToString());
            }
            Thread.Sleep(TimeSpan.FromSeconds(4));
            //線程終止
            t.Abort();

            Console.WriteLine("線程終止");
            Console.WriteLine(string.Format("t線程狀態:{0}", t.ThreadState.ToString()));
            Console.WriteLine(string.Format("t2線程狀態:{0}", t2.ThreadState.ToString()));
            Console.Read();
        }
 

        static void DoNothing()
        {
            Console.WriteLine("第五個多線程程式開始。。。。Second:" + DateTime.Now.Second);
            Thread.Sleep(TimeSpan.FromSeconds(2));
        }

        /// <summary>
        /// 暫停2秒的方法
        /// </summary>
        static void PrintNumberStatus()
        {
            Console.WriteLine("第五個多線程檢測狀態程式開始。。。。" + Thread.CurrentThread.ThreadState.ToString());
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine(string.Format("Second:{0} ==  {1}", DateTime.Now.Second, i));
                Thread.Sleep(TimeSpan.FromSeconds(2)); 

            }
        }
    }
}

2.程式執行結果如下

 

 如上圖,主線程啟動時定義了兩個子線程,一個會被終止,另一個會運行至結束。當我們啟動了線程之後,t2線程的狀態就會變成Running,然後會變成WaitSleepJoin,直到運行結束,變成Stopped。另一個t線程則會列印出數字來,當我們調用了abort方法之後,則t線程的狀態就變成了AbortRequested。這充分說明瞭同步兩個線程的複雜性,請不要程式中使用abort來終止線程。

 

七、線程優先順序(Priority

1.代碼如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading; //引入線程
using System.Diagnostics; 

namespace ThreadConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("開始,當前線程的優先順序:"+Thread.CurrentThread.Priority);
            Console.WriteLine("線程運行多核CPU上");
            //啟動線程
            Run();  
            Thread.Sleep(TimeSpan.FromSeconds(2));
 

            //單核模擬
            Console.WriteLine("線程運行單核CPU上");     

            Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(1);
            Run();
            Console.Read();

        }

 

        static void Run()
        {
            var demo = new ThreadRunDemo();
            Thread thread1 = new Thread(demo.CountNumber);
            thread1.Name = "ThreadOne";
            Thread thread2 = new Thread(demo.CountNumber);
            thread2.Name = "ThreadTwo";
            thread2.Priority = ThreadPriority.BelowNormal;
            Thread thread3 = new Thread(demo.CountNumber);
            thread3.Name = "ThreadThree";
 

            thread1.Priority = ThreadPriority.Highest;
            thread2.Priority = ThreadPriority.AboveNormal;
            thread3.Priority = ThreadPriority.Lowest; 

            thread1.Start();
            thread2.Start();
            thread3.Start();          

            Thread.Sleep(2000);
            demo.Stop();
        }
    }

    class ThreadRunDemo
    {
        private bool isStopped = false;
        public void Stop()
        {
            isStopped = true;
        }

        public void CountNumber()
        {
            long cnt = 0;
            while(!isStopped)
            {
                cnt++;
            }
            Console.WriteLine(string.Format("線程 {0} 的優先順序 {1,11} ,一共計算了 {2,13} 數字",
Thread.CurrentThread.Name,Thread.CurrentThread.Priority.ToString(), cnt.ToString("N0"))); } } }

2.程式執行結果如下

 

 從上圖的結果中,看出來當在多核CPU上運行多線程程式時,優先順序所起到的作用區別不大,以上圖的結果來看,最高優先順序與最低優先順序之間的差別在10%左右。如果在單核CPU上運行多線程程式時,優先順序的作用的特別明顯,以上圖的結果來看,最高優先順序與最低優先順序之間的差別在100倍以上。

 

八、前臺線程與後臺線程

1.代碼如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading; //引入線程
using System.Diagnostics; 

namespace ThreadConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {

            Console.WriteLine("開始,前臺線程與後臺線程");           

            var fore = new ThreadBackground(10);
            var back = new ThreadBackground(20);
            Thread threadF = new Thread(fore.CountNumber);
            threadF.Name = "前臺線程";
            Thread threadB = new Thread(back.CountNumber);

            threadB.Name = "後臺線程";
            threadB.IsBackground = true;
 

            //啟動線程
            threadF.Start();
            threadB.Start();
            //Console.Read(); 

        }
    }

    class ThreadBackground
    {
        private  int cnt ;
        public  ThreadBackground(int count)
        {
            cnt = count;
        }

        public void CountNumber()
        {
            for (int i = 0; i < cnt; i++)
            {
                Thread.Sleep(500);
                Console.WriteLine(string.Format("線程 {0} 列印 {1,11} 數字", Thread.CurrentThread.Name, i.ToString("N0")));
            }
            Console.WriteLine("{0} finished counting.",
                            Thread.CurrentThread.IsBackground ?
                            "Background Thread" : "Foreground Thread");        }
       
    }
}

 

2.程式執行結果

 

 根據上面的代碼,當程式執行到如上圖時,會一閃而過,退出。這是因為前臺線程已經執行結束,雖然後臺線程沒有執行結束,但程式會自動終止後臺線程。這就是前臺線程與後臺線程的區別,進程會等所有的前臺線程執行完畢,如果此時只剩下後臺線程沒有執行完畢,則會直接結束工作。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、查詢用戶及相應的角色 1.在Controller中修改Index方法,添加相關View, 顯示所有用戶。 (1) 將model作為參數傳過去,即在Index方法中,return返回(db.SysUsers) (2) 在Views ——Account —— Index.cshtml 中的頂部添加強 ...
  • 在網上有很多圖片都是gif,那麼如何在 wpf 解析 gif? 本文告訴大家如何使用 GifBitmapDecoder 把gif分開為一張一張,獲得他的信息 ...
  • 首先聲明:我對Lucene.Net並不熟悉,但搜索確實是分詞的一個重要應用,所以這裡還是嘗試將兩者集成起來,也許對你有一參考。 看到了兩個中文分詞與Lucene.Net的集成項目:Lucene.Net.Analysis.PanGu和Lucene.Net.Analysis.MMSeg,參考其中的代碼實 ...
  • 在應用程式目錄下配置mvc站點,會出現404錯誤,見下圖: 解決方式:給system.webServer節點下的models增加runAllManagedModulesForAllRequests="true" 參考:http://blog.csdn.net/nic7968/article/deta ...
  • 今天記錄一下學習Autofac的過程。 之前對IoC與DI一直很迷糊,今天研究了前輩們的文章後,才對IoC和DI有了一個初步的瞭解。感謝前輩們的無私奉獻! 文章地址: 依賴註入和控制反轉的理解,寫的太好了。 【第二章】 IoC 之 2.1 IoC基礎 ——跟我學Spring3 什麼鬼?明明是記錄Au ...
  • Application Application變數在整個應用程式生命周期中都是有效的,類似於使用全局變數一樣,所以可以在不同頁面中對它進行存取。它和Session變數的區別在於,前者是所有的用戶共用的全局變數,後者是各個用戶獨有的全局變數。 舉例來解釋: 網站訪問的計數器變數一般採用Applicat ...
  • /// <summary> /// Http下載文件 /// </summary> public void HttpDownloadFile(string url, string path) { // 設置參數 HttpWebRequest request = WebRequest.Create(u ...
  • 一、EF三種編程方式(在開始之前,先在VS2013中建立一個資料庫連接,如“EFDemo”) 1.“Database First” 即“資料庫優先模式”,前提是我們的應用已經有相應的資料庫。步驟如下: 新建項目,創建控制台應用程式(Visual c#)——改名稱:EFDemo——右鍵添加新項——選擇 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...