程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 線程系列01,前台線程,後台線程,線程同步,01前台

線程系列01,前台線程,後台線程,線程同步,01前台

編輯:C#入門知識

線程系列01,前台線程,後台線程,線程同步,01前台


在控制台應用程序集中,Main方法開始的是一個線程。如果要再創建線程,需要用到System.Threading這個命名空間。

 

□ 創建第一個線程

using System;
using System.Threading;
namespace ConsoleApplication4
{
    class Program
    {
        static void Main(string[] args)
        {
            var thread = new Thread(DoSth);
            thread.Start();
        }
        static void DoSth()
        {
            Console.WriteLine("我來自另外一個線程");
        }
    }
}

 

□ 前台線程和後台線程

新建的線程在默認情況下是前台線程,可以通過把IsBackground屬性設置為true,把線程定義為後台線程,一旦定義成後台線程,只要前台線程結束,無論後台線程是否結束,應用程序進程結束。

using System;
using System.Threading;
namespace ConsoleApplication4
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
            var thread = new Thread(DoSth);
            thread.IsBackground = true;
            thread.Start(1);
            Console.WriteLine("離開主線程");
        }
        static void DoSth(object threadId)
        {
            Console.WriteLine("我來自另外一個線程" + threadId);
        }
    }
}

○ ManagedThreadId屬性,托管線程Id,在進程內唯一,與操作系統的線程Id不是一回事。
○ Start方法可以帶參數,參數將被傳遞到線程方法
○ IsBackground屬性,設置線程是否為後台線程

 

□ 線程同步

※ 線程不同步的問題

假設主程序中有一個靜態變量,在主程序的方法內無限循環,每次讓該靜態變量自增1。

如果把該方法交給一個線程。

    class Program
    {
        private static int count = 0;
        static void Main(string[] args)
        {
            var t1 = new Thread(AddCount);
            t1.Start();
        }
        static void AddCount()
        {
            while (true)
            {
                int temp = count;
                Thread.Sleep(1000);
                count = temp + 1;
                Console.WriteLine("我的托管線程ID為:" + Thread.CurrentThread.ManagedThreadId + " 目前count的值為:" + count);
                Thread.Sleep(1000);
            }
        }
    }

運行良好,顯示的count值是連續遞增1。

 

如果把該方法交給2個線程。

    class Program
    {
        private static int count = 0;
        static void Main(string[] args)
        {
            var t1 = new Thread(AddCount);
            var t2 = new Thread(AddCount);
            t1.Start();
            t2.Start();
        }
        ......
    }

我們發現,count的值不是遞增。也就是說,count的值沒有做到同步。

→進入線程1,temp=0,線程1開始sleep
→進入線程2,temp=0,線程2開始sleep
→線程1"醒來",讓count=1,顯示count值為1,又sleep
→線程2"醒來",temp還是為0,所以count還是為1,顯示count值為1,又sleep
→如此循環
這裡的問題是:本想讓count一直遞增,但線程1和線程2沒有適時同步。如何解決呢?

 

※ 讓線程同步

使用lock語句塊,可以讓2個線程同步,讓每次只有一個線程進入程序執行的某個部分。

    class Program
    {
        private static int count = 0;
        static object o = new object();
        static void Main(string[] args)
        {
            var t1 = new Thread(AddCount);
            var t2 = new Thread(AddCount);
            t1.Start();
            t2.Start();
        }
        static void AddCount()
        {
            while (true)
            {
                lock (o)
                {
                    int temp = count;
                    Thread.Sleep(1000);
                    count = temp + 1;
                    Console.WriteLine("我的托管線程ID為:" + Thread.CurrentThread.ManagedThreadId + " 目前count的值為:" + count);
                }            
                Thread.Sleep(1000);
            }
        }
    }

 

總結:
○ 如果允許一個主線程結束,其它線程不管執行情況如何都結束,就把其它線程設置為後台線程。
○ lock語句塊能保證線程同步

 

線程系列包括:

線程系列01,前台線程,後台線程,線程同步

線程系列02,多個線程同時處理一個耗時較長的任務以節省時間

線程系列03,多線程共享數據,多線程不共享數據


對於前台線程與後台線程的一點疑問

說點自己理解的,希望對你有幫助。“運行完所有前台線程才可以退出”,意思就是進程的退出,更准確是當前應用程序域的退出。當你的主線程關閉,如果CLR檢測到還有其他前台線程,AppDomain會等待它的結束,然後調用unload方法,接下來清除資源,如果沒有其他應用程序域,進程也退出。這是一般的順序。至於你說的突然在任務管理器中將這個進程關閉了,當然可以讓他強制退出了,只不過是一種異常情況,如果還難理解,想象一下Kill掉進程,破壞掉內存,系統崩毀吧
 

main()線程是前台線程還是後台線程?前後台線程的不同是什?

main()函數即主函數,是一個前台線程,前台進程是程序中必須執行完成的,而後台線程則是java中所有前台結束後結束,不管有沒有完成,後台線程主要用與內存分配等方面,我知道就這些了
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved