乱涂C#多线程02

    技术2022-05-11  84

    【文章标题】: 乱涂C#多线程02 【文章作者】: 有酒醉 【作者邮箱】: wuqr32@sina.com 【下载地址】: 自己搜索下载 【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教! -------------------------------------------------------------------------------- 【详细过程】 采用线程池线程执行任务我们无法直接控制线程.有时我们想直接控制线程的行为,那么我们可以创建非线程池线程. //  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  managed __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  managed int  main() {    ThreadDelagate *td = new ThreadDelagate;    td->Start();    } 编译运行: 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 ID:996,State:Wait,Priority:Normal 通过枚举的方式我们发现该程序存在7个线程,但是在运行初期,我们通过任务管理器发现它的线程数才3个!这是什么原因呢?原来在枚举进程线程的操作实际上会使CLR创建更多的线程,用以执行此枚举操作!! <续> -------------------------------------------------------------------------------- 【版权声明】: 本文原创于泉州软件基地, 转载请注明作者并保持文章的完整, 谢谢!                                                        2007年02月07日 21:56:23

    最新回复(0)