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