文章出處

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

五、終止線程 (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.程序執行結果

 

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

 


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()