前言
在这之前,有很多人在质疑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定义的基本类型的函数可以在分线程运行