# 线程交叉访问助手
为确保脚本生命周期的执行顺序,辅助线程不能访问 Unity 的 API。但是,在使用多线程的过程中,有些线程会不可避免的调用 Unity 的 API,此时就需要制作一个助手类来解决这个问题。
# 代码部分
- 助手类只需要一个,所以使用单例模式
- 使用委托调用需要执行的代码
- 提供延时调用的功能
代码如下:
using System; | |
using System.Collections.Generic; | |
namespace Common | |
{ | |
/// <summary> | |
/// 线程交叉访问助手 | |
/// </summary> | |
public class ThreadCrossHelper : MonoSingleton<ThreadCrossHelper> | |
{ | |
/// <summary> | |
/// 行为信息类 | |
/// </summary> | |
private class ActionDelayItem | |
{ | |
/// <summary> | |
/// 行为 | |
/// </summary> | |
public Action Act; | |
/// <summary> | |
/// 延迟时间 | |
/// </summary> | |
public DateTime DelayTime; | |
/// <summary> | |
///true:可用 | |
/// </summary> | |
public bool Enabled; | |
/// <summary> | |
/// 创建行为信息 | |
/// </summary> | |
/// <param name="action"> 行为 & lt;/param> | |
/// <param name="time"> 延迟时间 & lt;/param> | |
public ActionDelayItem(Action action, DateTime time) | |
{ | |
Act = action; | |
DelayTime = time; | |
Enabled = true; | |
} | |
/// <summary> | |
/// 重置 | |
/// </summary> | |
/// <param name="action"> 行为 & lt;/param> | |
/// <param name="time"> 延迟时间 & lt;/param> | |
public void Reset(Action action, DateTime time) | |
{ | |
Act = action; | |
DelayTime = time; | |
Enabled = true; | |
} | |
} | |
/// <summary> | |
/// 行为列表 | |
/// </summary> | |
private List<ActionDelayItem> ActionList; | |
private void Start() | |
{ | |
ActionList = new List<ActionDelayItem>(); | |
} | |
private void Update() | |
{ | |
for (int i = ActionList.Count - 1; i >= 0; i--) | |
{ | |
if (ActionList[i].Enabled && DateTime.Now >= ActionList[i].DelayTime) | |
{ | |
ActionList[i].Act?.Invoke(); | |
ActionList[i].Enabled = false; | |
} | |
} | |
} | |
/// <summary> | |
/// 在主线程中调用指定的方法 | |
/// </summary> | |
/// <param name="act"> 委托 & lt;/param> | |
/// <param name="delay"> 延迟时间 & lt;/param> | |
public void ExecuteOnMainThread(Action act, float delay = 0) | |
{ | |
lock (ActionList) | |
{ | |
ActionDelayItem temp = ActionList.Find((iteam) => { return !iteam.Enabled; }); | |
if (temp != null) | |
{ | |
temp.Reset(act, DateTime.Now.AddSeconds(delay)); | |
} | |
else | |
{ | |
ActionList.Add(new ActionDelayItem(act, DateTime.Now.AddSeconds(delay))); | |
} | |
} | |
} | |
} | |
} |
# 使用方法
ThreadCrossHelper.Instance.ExecuteOnMainThread(() => | |
{ | |
Debug.Log("Test"); | |
}, 0); |