前言
在這之前,有很多人在質(zhì)疑Unity支不支持多線(xiàn)程,事實(shí)上Unity是支持多線(xiàn)程的。而提到多線(xiàn)程就要提到Unity非常常用的協(xié)程,然而協(xié)程并非真正的多線(xiàn)程。協(xié)程其實(shí)是等某個(gè)操作完成之后再執(zhí)行后面的代碼,或者說(shuō)是控制代碼在特定的時(shí)機(jī)執(zhí)行。而多線(xiàn)程在Unity渲染和復(fù)雜邏輯運(yùn)算時(shí)可以高效的使用多核CPU,幫助程序可以更高效的運(yùn)行。本篇主要介紹在Unity中如何使用多線(xiàn)程。
· 首先引入C#中使用多線(xiàn)程的類(lèi)庫(kù)
using System.Threading;
· 創(chuàng)建線(xiàn)程實(shí)例的四種方式
1.線(xiàn)程執(zhí)行無(wú)參方法
· 構(gòu)造語(yǔ)法
///
/// 初始化 Thread 類(lèi)的新實(shí)例。
///
///無(wú)參委托對(duì)象.
public Thread(ThreadStart start)
start
類(lèi)型:System.Threading.ThreadStart
表示開(kāi)始執(zhí)行此線(xiàn)程時(shí)要調(diào)用的方法的 ThreadStart 委托。
· 實(shí)例
void Start()
{
//創(chuàng)建無(wú)參線(xiàn)程對(duì)象
Thread thr = new Thread(Func_NoArguments);
//啟動(dòng)線(xiàn)程
thr.Start();
}
///
/// Function Of No Arguments.
///
void Func_NoArguments()
{
Debug.Log("Run Func_NoArguments");
}
2.線(xiàn)程執(zhí)行有參方法
· 構(gòu)造語(yǔ)法
///
/// 初始化 Thread 類(lèi)的新實(shí)例。
///
///有參委托對(duì)象.
public Thread(ParameterizedThreadStart start)
start
類(lèi)型:System.Threading.ParameterizedThreadStart
一個(gè)委托,它表示此線(xiàn)程開(kāi)始執(zhí)行時(shí)要調(diào)用的方法。
注意:參數(shù)只能有一個(gè),且必須為object類(lèi)型
· 實(shí)例
void Start()
{
//創(chuàng)建有參線(xiàn)程對(duì)象
Thread thr = new Thread(Func_Arguments);
//啟動(dòng)線(xiàn)程,傳入?yún)?shù)
thr.Start("Lanou");
}
///
/// Function Of Have Arguments.
///
void Func_Arguments(object data)
{
Debug.Log("Run Func_Arguments, Data = " + data);
}
3.線(xiàn)程執(zhí)行無(wú)參方法,限制線(xiàn)程要使用的最大堆棧大小
· 構(gòu)造語(yǔ)法
///
/// 初始化 Thread 類(lèi)的新實(shí)例。
///
///無(wú)參委托對(duì)象.
///使用的最大堆棧大小.
public Thread(ThreadStart start,int maxStackSize)
start
類(lèi)型:System.Threading.ThreadStart
表示開(kāi)始執(zhí)行此線(xiàn)程時(shí)要調(diào)用的方法的 ThreadStart 委托。
maxStackSize
類(lèi)型:System.Int32
線(xiàn)程要使用的最大堆棧大小(以字節(jié)為單位);如果為 0,則使用可執(zhí)行文件的文件頭中指定的默認(rèn)最大堆棧大小。
重要事項(xiàng):對(duì)于部分受信任的代碼,如果 maxStackSize 大于默認(rèn)堆棧大小,則將其忽略。 不引發(fā)異常。
· 實(shí)例
void Start()
{
//創(chuàng)建無(wú)參線(xiàn)程對(duì)象,限制256KB堆棧大小
Thread thr = new Thread(Func_NoArguments,262144);
//啟動(dòng)線(xiàn)程
thr.Start();
}
///
/// Function Of No Arguments.
///
void Func_NoArguments()
{
Debug.Log("Run Func_NoArguments");
}
4.線(xiàn)程執(zhí)行有參方法,限制線(xiàn)程要使用的最大堆棧大小
· 構(gòu)造語(yǔ)法
///
/// 初始化 Thread 類(lèi)的新實(shí)例。
///
///有參委托對(duì)象.
///使用的最大堆棧大小.
public Thread(ParameterizedThreadStart start,int maxStackSize)
start
類(lèi)型:System.Threading.ParameterizedThreadStart
一個(gè)委托,它表示此線(xiàn)程開(kāi)始執(zhí)行時(shí)要調(diào)用的方法。
注意:參數(shù)只能有一個(gè),且必須為object類(lèi)型
maxStackSize
類(lèi)型:System.Int32
線(xiàn)程要使用的最大堆棧大小(以字節(jié)為單位);如果為 0,則使用可執(zhí)行文件的文件頭中指定的默認(rèn)最大堆棧大小。
重要事項(xiàng):對(duì)于部分受信任的代碼,如果 maxStackSize 大于默認(rèn)堆棧大小,則將其忽略。 不引發(fā)異常。
· 實(shí)例
void Start()
{
//創(chuàng)建有參線(xiàn)程對(duì)象,限制256KB堆棧大小
Thread thr = new Thread(Func_Arguments,262144);
//啟動(dòng)線(xiàn)程,傳入?yún)?shù)
thr.Start("Lanou");
}
///
/// Function Of Have Arguments.
///
void Func_Arguments(object data)
{
Debug.Log("Run Func_Arguments, Data = " + data);
}
· 啟動(dòng)線(xiàn)程(上文已使用)
· 無(wú)參啟動(dòng)
void Start()
{
//創(chuàng)建無(wú)參線(xiàn)程對(duì)象
Thread thr = new Thread(Func_NoArguments);
//啟動(dòng)線(xiàn)程
thr.Start();
}
/// <summary>
/// Function Of No Arguments.
/// </summary>
void Func_NoArguments()
{
Debug.Log("Run Func_NoArguments");
}
· 有參啟動(dòng)
void Start()
{
//創(chuàng)建有參線(xiàn)程對(duì)象
Thread thr = new Thread(Func_Arguments);
//啟動(dòng)線(xiàn)程,傳入?yún)?shù)
thr.Start("Lanou");
}
/// <summary>
/// Function Of Have Arguments.
/// </summary>
void Func_Arguments(object data)
{
Debug.Log("Run Func_Arguments, Data = " + data);
}
· 常用方法
· public static void Sleep( int millisecondsTimeout)將當(dāng)前線(xiàn)程掛起指定的毫秒數(shù)。
millisecondsTimeout
millisecondsTimeout
類(lèi)型:System.Int32
掛起線(xiàn)程的毫秒數(shù)。 如果 millisecondsTimeout 參數(shù)的值為零,則該線(xiàn)程會(huì)將其時(shí)間片的剩余部分讓給任何已經(jīng)準(zhǔn)備好運(yùn)行的、有同等優(yōu)先級(jí)的線(xiàn)程。 如果沒(méi)有其他已經(jīng)準(zhǔn)備好運(yùn)行的、具有同等優(yōu)先級(jí)的線(xiàn)程,則不會(huì)掛起當(dāng)前線(xiàn)程的執(zhí)行。
· public void Resume()
繼續(xù)已掛起的線(xiàn)程。(已過(guò)時(shí))
· public void Abort()
在調(diào)用此方法的線(xiàn)程上引發(fā) ThreadAbortException,以開(kāi)始終止此線(xiàn)程的過(guò)程。 調(diào)用此方法通常會(huì)終止線(xiàn)程。
· public void Join()
阻止調(diào)用線(xiàn)程直到線(xiàn)程終止,同時(shí)繼續(xù)執(zhí)行標(biāo)準(zhǔn)的 COM 和 SendMessage 傳送。
· public enum ThreadPriority
指定 Thread 的調(diào)度優(yōu)先級(jí)。
成員名稱(chēng) |
描述 |
AboveNormal |
可以將 Thread 安排在具有 Highest 優(yōu)先級(jí)的線(xiàn)程之后,在具有 Normal 優(yōu)先級(jí)的線(xiàn)程之前。 |
BelowNormal |
可以將 Thread 安排在具有 Normal 優(yōu)先級(jí)的線(xiàn)程之后,在具有 Lowest 優(yōu)先級(jí)的線(xiàn)程之前。 |
Highest |
可以將 Thread 安排在具有任何其他優(yōu)先級(jí)的線(xiàn)程之前。 |
Lowest |
可以將 Thread 安排在具有任何其他優(yōu)先級(jí)的線(xiàn)程之后。 |
Normal |
可以將 Thread 安排在具有 AboveNormal 優(yōu)先級(jí)的線(xiàn)程之后,在具有 BelowNormal 優(yōu)先級(jí)的線(xiàn)程之前。 默認(rèn)情況下,線(xiàn)程具有 Normal 優(yōu)先級(jí)。 |
· 通過(guò)線(xiàn)程池執(zhí)行線(xiàn)程
· ThreadPool.QueueUserWorkItem 方法 (WaitCallback)
public static bool QueueUserWorkItem(WaitCallback callBack)
callBack
類(lèi)型:System.Threading.WaitCallback
一個(gè) WaitCallback,表示要執(zhí)行的方法。
返回值
類(lèi)型:System.Boolean
如果此方法成功排隊(duì),則為 true;如果無(wú)法將該工作項(xiàng)排隊(duì),則引發(fā) NotSupportedException。
· Unity使用多線(xiàn)程注意
0. 變量都是共享的(都能指向相同的內(nèi)存地址)
1. UnityEngine的API不能在分線(xiàn)程運(yùn)行
2. UnityEngine定義的基本結(jié)構(gòu)(int,float,Struct定義的數(shù)據(jù)類(lèi)型)可以在分線(xiàn)程計(jì)算,如 Vector3(Struct)可以 , 但Texture2d(class,根父類(lèi)為Object)不可以。
3. UnityEngine定義的基本類(lèi)型的函數(shù)可以在分線(xiàn)程運(yùn)行