1. 程式人生 > >Unity主線程和子線程跳轉調用(2)

Unity主線程和子線程跳轉調用(2)

date har body edit 繼續 clas turn lec 任務

  在上一篇介紹了多線程和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 }

Unity主線程和子線程跳轉調用(2)