天天看点

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

继续阅读