位置:首頁 > 高級語言 > C#教學 > C#多線程

C#多線程

一個線程被定義為程序的執行路徑。每個線程限定控製的一個獨特的流程。如果你的應用涉及到複雜的和耗時的操作,那麼它往往是有幫助的,設置不同的執行路徑或線程,每個線程以執行特定工作。

線程是輕量級進程。使用線程中的一個常見的例子是由現代操作係統執行並發編程的。使用線程CPU節省周期和應用的增加效率。

到目前為止,我們已經編寫的程序在一個單一的線程運行作為一個單一的過程,是應用程序的運行實例。然而,這種方式的應用程序可以在一個時間執行一個作業。使它在一個時間執行多個任務時,它可以被分成更小的線程。

線程生命周期

在創建System.Threading.Thread類的對象時,一個線程的生命周期開始和結束時,該線程被終止或完成執行。

以下是在一個線程的生命周期中的各種狀態:

  • 未啟動狀態: 它是這種情況,創建的線程的實例,但在開始方法尚未被調用時。

  • 就緒狀態: 它的情況是當線程準備運行,等待CPU周期。

  • 不可運行狀態:線程冇有運行的時候:

    • 睡眠方法被調用

    • wait方法被調用

    • 通過I/O操作受阻

  • 死亡狀態:這是當線程執行完畢或已中止的情況。

主線程

在C#中,System.Threading.Thread類是用於與線程的工作。它允許創建和訪問在多線程應用程序單個線程。在一個過程中被執行的第一線程稱為主線程。

當一個C#程序開始執行,主線程會自動創建。使用Thread類創建的線程被稱為主線程的子線程。可以使用Thread類的CurrentThread屬性來訪問一個線程。

下麵的程序演示主線程的執行:

using System;
using System.Threading;

namespace MultithreadingApplication
{
    class MainThreadProgram
    {
        static void Main(string[] args)
        {
            Thread th = Thread.CurrentThread;
            th.Name = "MainThread";
            Console.WriteLine("This is {0}", th.Name);
            Console.ReadKey();
        }
    }
}

當上述代碼被編譯和執行時,它產生了以下結果:

This is MainThread

常用Thread類的屬性和方法

下表顯示了一些Thread類中最常用的屬性:

屬性 描述
CurrentContext 獲取在該線程正在執行的當前上下文
CurrentCulture 獲取或設置當前線程的culture
CurrentPrinciple 獲取或設置線程的當前主體(基於角色的安全性)
CurrentThread 獲取當前正在運行的線程
CurrentUICulture 獲取或設置使用資源管理器來查找區域性特定資源在運行時的當前culture
ExecutionContext 獲取包含有關當前線程的各種上下文信息的ExecutionContext對象
IsAlive 獲取一個指示當前線程的執行狀態
IsBackground 獲取或設置一個值,指示線程是否是後台線程
IsThreadPoolThread 獲取一個值,指示線程是否不屬於管理線程池
ManagedThreadId 獲取當前托管線程的唯一標識符
Name 獲取或設置線程的名稱
Priority 獲取或設置一個值,指示線程的調度優先級
ThreadState 獲取包含當前線程的狀態的值

下表顯示了一些Thread類中最常用的方法:

S.N 方法名稱和說明
1 public void Abort()
提高在其上調用它的線程一個ThreadAbortException,以開始終止線程的過程。調用此方法通常會終止線程
2 public static LocalDataStoreSlot AllocateDataSlot()
分配所有線程一未命名的數據插槽。為了獲得更好的性能,即標有ThreadStaticAttribute使用字段屬性來代替
3 public static LocalDataStoreSlot AllocateNamedDataSlot( string name) 
分配上的所有線程命名的數據槽。為了獲得更好的性能,即標有ThreadStaticAttribute使用字段屬性來代替
4 public static void BeginCriticalRegion()
通知主機的執行是即將進入代碼區域,其中一個線程的影響中止未處理的異常的區域可能會危及應用程序域中的其他任務
5 public static void BeginThreadAffinity()
通知的主機托管代碼將要執行依賴於當前物理操作係統線程的身份的指示
6 public static void EndCriticalRegion()
通知的主機執行即將進入的或代碼,其中一個線程的效果中止未處理的異常的區域被限製在當前的任務
7 public static void EndThreadAffinity()
通知的主機托管代碼已完成執行依賴於當前的物理操作係統線程的身份的指示
8 public static void FreeNamedDataSlot(string name)
消除了名稱和插槽之間的關聯,對於在這個過程中的所有線程。為了獲得更好的性能,即標有ThreadStaticAttribute使用字段屬性來代替
9 public static Object GetData( LocalDataStoreSlot slot ) 
檢索從當前線程上指定槽位的值,在當前線程的當前域內。為了獲得更好的性能,即標有ThreadStaticAttribute使用字段屬性來代替
10 public static AppDomain GetDomain()
返回在當前線程運行的當前域
11 public static AppDomain GetDomain()
返回一個唯一的應用程序域標識符
12 public static LocalDataStoreSlot GetNamedDataSlot( string name ) 
查找一個命名的數據槽。為了獲得更好的性能,即標有ThreadStaticAttribute使用字段屬性來代替
13 public void Interrupt()
中斷線程WaitSleepJoin線程狀態
14 public void Join()
阻塞調用線程,直到某個線程終止,同時繼續執行標準的COM和SendMessage消息處理。這種方法有不同的重載形式
15 public static void MemoryBarrier()
同步存儲器存取如下:該內存之前調用MemoryBarrier訪問該處理器執行當前線程不能重新排序以這樣的方式執行的指令之後的存儲器訪問隨後的調用MemoryBarrier
16 public static void ResetAbort()
取消中止請求當前線程
17 public static void SetData( LocalDataStoreSlot slot, Object data ) 
設置數據中當前運行的線程上指定槽位,在線程的當前域。為了獲得更好的性能,ThreadStaticAttribute使用字段屬性來代替
18 public void Start()
開始一個線程
19 public static void Sleep( int millisecondsTimeout ) 
使線程暫停一段時間
20 public static void SpinWait( int iterations ) 
導致一個線程等待由迭代參數定義的次數
21 public static byte VolatileRead( ref byte address )
public static double VolatileRead( ref double address )
public static int VolatileRead( ref int address )
public static Object VolatileRead( ref Object address ) 

讀取一個字段的值。的值是最新的寫入通過在計算機的任何處理器,而不管處理器數或處理器高速緩衝存儲器的狀態的。這種方法有不同的重載形式。隻有一些在上文給出
22 public static void VolatileWrite( ref byte address, byte value )
public static void VolatileWrite( ref double address, double value )
public static void VolatileWrite( ref int address, int value )
public static void VolatileWrite( ref Object address, Object value ) 

寫入一個值,以立即的字段,使得值是可見的計算機中的所有處理器。這種方法有不同的重載形式。隻有一些在上文給出
23 public static bool Yield()
導致調用線程產生執行到另一個線程準備在當前處理器上運行。操作係統的選擇產生的線程

創建線程

線程是通過繼承Thread類創建。擴展Thread類,然後調用start()方法來開始子線程執行。

下麵的程序演示的概念:

using System;
using System.Threading;

namespace MultithreadingApplication
{
    class ThreadCreationProgram
    {
        public static void CallToChildThread()
        {
            Console.WriteLine("Child thread starts");
        }
        
        static void Main(string[] args)
        {
            ThreadStart childref = new ThreadStart(CallToChildThread);
            Console.WriteLine("In Main: Creating the Child thread");
            Thread childThread = new Thread(childref);
            childThread.Start();
            Console.ReadKey();
        }
    }
}

當上述代碼被編譯和執行時,它產生了以下結果:

In Main: Creating the Child thread
Child thread starts

管理線程

Thread類提供了各種方法來管理線程。

下麵的例子說明了如何使用sleep()方法的用於製造線程暫停一段特定的時間。

using System;
using System.Threading;

namespace MultithreadingApplication
{
    class ThreadCreationProgram
    {
        public static void CallToChildThread()
        {
            Console.WriteLine("Child thread starts");
            // the thread is paused for 5000 milliseconds
            int sleepfor = 5000; 
            Console.WriteLine("Child Thread Paused for {0} seconds", 
                              sleepfor / 1000);
            Thread.Sleep(sleepfor);
            Console.WriteLine("Child thread resumes");
        }
        
        static void Main(string[] args)
        {
            ThreadStart childref = new ThreadStart(CallToChildThread);
            Console.WriteLine("In Main: Creating the Child thread");
            Thread childThread = new Thread(childref);
            childThread.Start();
            Console.ReadKey();
        }
    }
}

當上述代碼被編譯和執行時,它產生了以下結果:

In Main: Creating the Child thread
Child thread starts
Child Thread Paused for 5 seconds
Child thread resumes

銷毀線程

Abort()方法用於銷毀線程。

運行時拋出一個ThreadAbortException中止線程。該異常不能被捕獲,控製發送到finally塊(如果有)。

下麵的程序說明了這一點:

using System;
using System.Threading;

namespace MultithreadingApplication
{
    class ThreadCreationProgram
    {
        public static void CallToChildThread()
        {
            try
            {

                Console.WriteLine("Child thread starts");
                // do some work, like counting to 10
                for (int counter = 0; counter <= 10; counter++)
                {
                    Thread.Sleep(500);
                    Console.WriteLine(counter);
                }
                Console.WriteLine("Child Thread Completed");

            }
            catch (ThreadAbortException e)
            {
                Console.WriteLine("Thread Abort Exception");
            }
            finally
            {
                Console.WriteLine("Couldn't catch the Thread Exception");
            }

        }
        
        static void Main(string[] args)
        {
            ThreadStart childref = new ThreadStart(CallToChildThread);
            Console.WriteLine("In Main: Creating the Child thread");
            Thread childThread = new Thread(childref);
            childThread.Start();
            //stop the main thread for some time
            Thread.Sleep(2000);
            //now abort the child
            Console.WriteLine("In Main: Aborting the Child thread");
            childThread.Abort();
            Console.ReadKey();
        }
    }
}

讓我們編譯和運行上麵的程序,這將產生以下結果:

In Main: Creating the Child thread
Child thread starts
0
1
2
In Main: Aborting the Child thread
Thread Abort Exception
Couldn't catch the Thread Exception