【詳細過程】
采用線程池線程執行任務我們無法直接控制線程.有時我們想直接控制線程的行為,那麼我們可以建立非線程池線程.
// 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