在上一篇介绍了多线程和Unity交互方式,但是由于我的项目是一个unity编辑器插件项目,很显然上一篇的代码需要加以修改,在编辑器下实现Loom.
1,Editor下的没有Update这个生命周期函数,但是Ediitor提供了EditorApplication.update这个事件,自己用这个事件订阅update方法即可
2,Editor下的没有Awake OnDestory这些生命周期函数,需要自己编写方法让外部去创建、销毁Loom
3, 我的项目需要保证子线程逻辑不假死的同时又要保证同步,如下面这段伪代码,执行顺序为:DownFile1->UnityFunction1->DownFile2->UnityFunction2
Function { //异步在多线程下运行 Loom.RunAsync(() => { //耗时函数 DownFile1(); //回到unity线程继续运行 Loom.QueueOnMainThread(()=> { //这个函数是unity函数 UnityFunction1(); } //耗时函数 DownFile2(); //回到unity线程继续运行 Loom.QueueOnMainThread(()=> { //这个函数是unity函数 UnityFunction2(); } } }
修改后的代码如下
1 using UnityEngine; 2 using System.Collections; 3 using System.Collections.Generic; 4 using System; 5 using System.Threading; 6 using System.Linq; 7 using UnityEditor; 8 public class Loom 9 { 10 /// <summary> 11 /// 当前是否有unity任务需要执行 12 /// </summary> 13 static bool hasUnityAction = true; 14 15 private static Thread loomThread; 16 17 /// <summary> 18 /// unity任务表 19 /// </summary> 20 private List<Action> actions = new List<Action>(); 21 22 #region 单例 注册update事件 23 private static Loom _instance; 24 private static readonly object lockObj = new object(); 25 public static Loom Current 26 { 27 get 28 { 29 if (_instance == null) 30 { 31 lock (lockObj) 32 { 33 if (_instance == null) 34 { 35 _instance = new Loom(); 36 } 37 38 } 39 } 40 return _instance; 41 } 42 } 43 private Loom() 44 { 45 EditorApplication.update += Update; 46 47 } 48 #endregion 49 50 51 52 53 /// <summary> 54 /// 子线程启动一个任务 55 /// </summary> 56 /// <param name="a"></param> 57 /// <returns></returns> 58 public Thread RunAsync(Action a) 59 { 60 if (loomThread != null) 61 { 62 Stop(); 63 throw new Exception("任务仅运行一次"); 64 } 65 loomThread = new Thread(new ParameterizedThreadStart(RunAction)); 66 loomThread.Name = "Loom线程"; 67 loomThread.Priority = System.Threading.ThreadPriority.Lowest; 68 loomThread.Start(a); 69 return loomThread; 70 } 71 /// <summary> 72 /// 加入一个任务到主线程队列 73 /// </summary> 74 /// <param name="action"></param> 75 public void QueueOnMainThread(Action action) 76 { 77 if (Current != null && Thread.CurrentThread == loomThread) 78 { 79 hasUnityAction = true; 80 lock (Current.actions) 81 { 82 Current.actions.Add(action); 83 } 84 while (hasUnityAction) 85 { 86 loomThread.Priority = System.Threading.ThreadPriority.Lowest; 87 Thread.Sleep(10); 88 } 89 } 90 91 } 92 93 /// <summary> 94 /// 延迟子线程 95 /// </summary> 96 /// <param name="time"></param> 97 public void Sleep(int time) 98 { 99 if (Current != null && Thread.CurrentThread == loomThread) 100 { 101 Thread.Sleep(time); 102 103 } 104 } 105 106 /// <summary> 107 /// 停止任务 108 /// </summary> 109 public void Stop() 110 { 111 EditorApplication.update -= Update; 112 try 113 { 114 loomThread.Abort(); 115 } 116 catch (Exception e) 117 { 118 Debug.Log(e.ToString()); 119 } 120 finally 121 { 122 loomThread = null; 123 _instance = null; 124 } 125 126 } 127 128 129 130 private void RunAction(object action) 131 { 132 try 133 { 134 ((Action)action)(); 135 } 136 catch 137 { 138 } 139 140 } 141 142 List<Action> _currentActions = new List<Action>(); 143 144 static void Update() 145 { 146 try 147 { 148 149 150 if (!hasUnityAction) return; 151 152 lock (Current.actions) 153 { 154 Current._currentActions.Clear(); 155 Current._currentActions.AddRange(Current.actions); 156 Current.actions.Clear(); 157 } 158 for (int i = 0; i < Current._currentActions.Count; i++) 159 { 160 Debug.LogError("主线程任务"); 161 Current._currentActions[i](); 162 163 } 164 hasUnityAction = false; 165 } 166 catch 167 { 168 Debug.LogError("主线程任务失败"); 169 } 170 } 171 }