天天看點

C# 擷取多線程ID

【詳細過程】

采用線程池線程執行任務我們無法直接控制線程.有時我們想直接控制線程的行為,那麼我們可以建立非線程池線程.

// ThreadDemo.cs  
// Author by Yzl  

using System;  
using System.Threading;  

public class ThreadDemo  
{  
    public static void Main(string[] args)  
    {  
        Thread t = new Thread(new ThreadStart(ThreadProc));  
        t.Start();         
        Console.WriteLine("Priority:" + t.Priority);  
        Console.WriteLine("ThreadState:" + t.ThreadState);  
        for (int i = 0; i < 5; i ++)  
        {  
            Console.WriteLine("Hello Main");  
            Thread.Sleep(100);  
        }  
    }  

    private static void ThreadProc()  
    {  
        for (int i = 0;i < 5; i ++)  
        {  
            Console.WriteLine("Hello ThreadProc");  
            Thread.Sleep(500);  
        }  
    }  
}      

編譯運作:

D:>csc ThreadDemo.cs

Microsoft (R) Visual C# .NET 編譯器版本 7.10.6001.4

用于 Microsoft (R) .NET Framework 版本 1.1.4322

版權所有 (C) Microsoft Corporation 2001-2002。保留所有權利。

D:>ThreadDemo

Hello ThreadProc

Priority:Normal

ThreadState:WaitSleepJoin

Hello Main

Hello Main

Hello Main

Hello Main

Hello Main

Hello ThreadProc

Hello ThreadProc

Hello ThreadProc

Hello ThreadProc

前台線程和背景線程:線程池線程都是背景線程,一般線程建立時預設為前台線程,可以通過Thread.IsBackground屬性進行更改.一旦程式中不再有前台線程,Windows将終止該程式.

我們先來看看前台線程

// ThreadDemo.cs  
// Author by Yzl  

using System;  
using System.Threading;  

public class ThreadDemo  
{  
    public static void Main(string[] args)  
    {  
        Thread t = new Thread(new ThreadStart(ThreadProc));  
        t.Name = "CustomThread";  
        //t.IsBackground = true;  
        t.Start();      
    }  

    private static void ThreadProc()  
    {  
        for (int i = 0;i < 5; i ++)  
        {  
            Console.WriteLine("Hello ThreadProc");  
            Thread.Sleep(800);  
        }  
    }  
}      

D:>csc ThreadDemo.cs

D:>ThreadDemo

Hello ThreadProc

Hello ThreadProc

Hello ThreadProc

Hello ThreadProc

Hello ThreadProc

奇怪!程式并未調用Thread.Join()方法,自定義線程也一樣執行完.正常情況下t.Start()執行完後Main也就終結了,整個程式應該退出才是!

接下來我們測試一下背景線程,将下面代碼的注釋去掉:

//t.IsBackground = true;

重新運作看效果:

D:>csc ThreadDemo.cs

D:>ThreadDemo

D:>

什麼結果也沒有!!換句話說,隻要有一個前台線程,不管Main上代碼是否都已經執行,它也将等待其他前台線程執行完畢才退出.如果Main上的代碼都已執行同時不存在前台線程,那麼程式自動退出.

同樣還有一個問題存在,我們更改一下上面的程式:

// ThreadDemo.cs  
// Author by Yzl  

using System;  
using System.Threading;  

public class ThreadDemo  
{  
    public static void Main(string[] args)  
    {  
        Thread t = new Thread(new ThreadStart(ThreadProc));  
        t.Name = "CustomThread";  
        Thread.CurrentThread.IsBackground = true; // 注意!設定主線程為背景線程!  
        Console.WriteLine("the t of thread is Background:" + t.IsBackground); // 注意!  
        t.Start();      
    }  

    private static void ThreadProc()  
    {  
        for (int i = 0;i < 5; i ++)  
        {  
            Console.WriteLine("Hello ThreadProc");  
            Thread.Sleep(800);  
        }  
    }  
}      

編譯運作:

D:>csc ThreadDemo.cs

Microsoft (R) Visual C# .NET 編譯器版本 7.10.6001.4

用于 Microsoft (R) .NET Framework 版本 1.1.4322

版權所有 (C) Microsoft Corporation 2001-2002。保留所有權利。

D:>ThreadDemo

the t of thread is Background:False

D:>

問題1:如果按我們剛才的了解,t是前台線程,Main理應等待線程t完全執行完畢才是,但是結果卻什麼也沒輸出!這是什麼緣故?暫時還沒研究出答案,待我們深入探讨之後在回頭看這個問題

非托管線程是通過線程ID來辨別的,托管線程則通過散列代碼(Thread.GetHashCode())或名稱(Thread.Name)來辨別.擷取目前線程ID采用AppDomain.GetCurrentThreadId().

示例-擷取線程ID

// T.cpp  
// Author by Yzl  

#include < stdio.h >   
#using < mscorlib.dll >  
using namespace System::Threading;  

#pragma
__gc class ThreadDelagate  
{  
    public:  
        void Start()  
        {  
            ThreadStart *ts = new ThreadStart(this,ThreadProc);  
            Thread* myThread = new Thread(ts);      
            myThread->Start();  
        }  
    private:  
        void ThreadProc()  
        {  
            printf("Thread id:%d",System::AppDomain::GetCurrentThreadId());      
        }          
};  

#pragma
int main()  
{  
    ThreadDelagate *td = new      

編譯運作:

D:>cl /clr T.cpp

Microsoft (R) C/C++ Optimizing Compiler Version 13.10.3077 for .NET Framework

Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.

T.cpp

Microsoft (R) Incremental Linker Version 7.10.3077

Copyright (C) Microsoft Corporation. All rights reserved.

/out:T.exe

T.obj

D:>T

Thread id:1800

D:>

注意!如果将main更改為:

#pragma unmanaged

int main()

{

ThreadDelagate *td = new ThreadDelagate;

td->Start();          

}

編譯将得到如下錯誤:

error C3821: “ThreadDelagate” : 托管類型不能用于非托管函數

error C3169: “td” : 在非托管函數内不能聲明托管對象或 __gc 指針

error C3821: “ThreadDelagate” : 托管類型不能用于非托管函數

error C3175: “ThreadDelagate::ThreadDelagate” : 不能從非托管函數“main”調用托管類型的方法

error C3821: “td” : 托管類型不能用于非托管函數

error C3175: “ThreadDelagate::Start” : 不能從非托管函數“main”調用托管類型的方法

原因我就不多講.很明朗!是以,如果要操縱托管線程ID,需先把它儲存起來,然後在非托管代碼中進行應用.

示例-枚舉非托管線程(ProcessThread表示作業系統程序線程)

// ProcessThreadDemo.cs  
// Author by Yzl  

using System;  
using System.Diagnostics;  

public class ProcessThreadDemo  
{  
    public static void Main(string[] args)  
    {  
        Console.ReadLine();  
        ProcessThreadCollection ptCollection = Process.GetCurrentProcess().Threads;  
        Console.WriteLine("{0} threads in process",ptCollection.Count);     
        foreach (ProcessThread pt in ptCollection)  
        {  
            Console.WriteLine("ID:{0},State:{1},Priority:{2}",pt.Id,pt.ThreadState,pt.PriorityLevel);  
        }  
    }  
}      

編譯運作:

D:>ProcessThreadDemo

h

7 threads in process

ID:3700,State:Running,Priority:Normal

ID:1076,State:Wait,Priority:Normal

ID:452,State:Wait,Priority:Highest

ID:2292,State:Wait,Priority:Normal

ID:3872,State:Wait,Priority:Normal

ID:2952,State:Wait,Priority:Normal

繼續閱讀