Unity多線程(C#)

前言

在這之前,有很多人在質(zhì)疑Unity支不支持多線程宫仗,事實(shí)上Unity是支持多線程的彻坛。而提到多線程就要提到Unity非常常用的協(xié)程,然而協(xié)程并非真正的多線程荐虐。協(xié)程其實(shí)是等某個(gè)操作完成之后再執(zhí)行后面的代碼七兜,或者說(shuō)是控制代碼在特定的時(shí)機(jī)執(zhí)行。而多線程在Unity渲染和復(fù)雜邏輯運(yùn)算時(shí)可以高效的使用多核CPU福扬,幫助程序可以更高效的運(yùn)行腕铸。本篇主要介紹在Unity中如何使用多線程。


  • 首先引入C#中使用多線程的類庫(kù)
    using System.Threading;

  • 創(chuàng)建線程實(shí)例的四種方式
    1.線程執(zhí)行無(wú)參方法

    • 構(gòu)造語(yǔ)法
      /// <summary>
      /// 初始化 Thread 類的新實(shí)例铛碑。
      /// </summary>
      /// <param name="start">無(wú)參委托對(duì)象.</param>
      public Thread(ThreadStart start)
      start
      類型:System.Threading.ThreadStart
      表示開(kāi)始執(zhí)行此線程時(shí)要調(diào)用的方法的 ThreadStart 委托狠裹。
    • 實(shí)例
      void Start()
      {
      //創(chuàng)建無(wú)參線程對(duì)象
      Thread thr = new Thread(Func_NoArguments);
      //啟動(dòng)線程
      thr.Start();
      }
      /// <summary>
      /// Function Of No Arguments.
      /// </summary>
      void Func_NoArguments()
      {
      Debug.Log("Run Func_NoArguments");
      }

    2.線程執(zhí)行有參方法

    • 構(gòu)造語(yǔ)法
      /// <summary>
      /// 初始化 Thread 類的新實(shí)例。
      /// </summary>
      /// <param name="start">有參委托對(duì)象.</param>
      public Thread(ParameterizedThreadStart start)
      start
      類型:System.Threading.ParameterizedThreadStart
      一個(gè)委托汽烦,它表示此線程開(kāi)始執(zhí)行時(shí)要調(diào)用的方法涛菠。
      注意:參數(shù)只能有一個(gè),且必須為object類型
    • 實(shí)例
      void Start()
      {
      //創(chuàng)建有參線程對(duì)象
      Thread thr = new Thread(Func_Arguments);
      //啟動(dòng)線程,傳入?yún)?shù)
      thr.Start("Lanou");
      }
      /// <summary>
      /// Function Of Have Arguments.
      /// </summary>
      void Func_Arguments(object data)
      {
      Debug.Log("Run Func_Arguments, Data = " + data);
      }

    3.線程執(zhí)行無(wú)參方法,限制線程要使用的最大堆棧大小

    • 構(gòu)造語(yǔ)法
      /// <summary>
      /// 初始化 Thread 類的新實(shí)例俗冻。
      /// </summary>
      /// <param name="start">無(wú)參委托對(duì)象.</param>
      /// <param name="maxStackSize">使用的最大堆棧大小.</param>
      public Thread(ThreadStart start,int maxStackSize)
      start
      類型:System.Threading.ThreadStart
      表示開(kāi)始執(zhí)行此線程時(shí)要調(diào)用的方法的 ThreadStart 委托礁叔。
      maxStackSize
      類型:System.Int32
      線程要使用的最大堆棧大小(以字節(jié)為單位)言疗;如果為 0晴圾,則使用可執(zhí)行文件的文件頭中指定的默認(rèn)最大堆棧大小。
      重要事項(xiàng):對(duì)于部分受信任的代碼噪奄,如果 maxStackSize 大于默認(rèn)堆棧大小死姚,則將其忽略。 不引發(fā)異常勤篮。
    • 實(shí)例
      void Start()
      {
      //創(chuàng)建無(wú)參線程對(duì)象,限制256KB堆棧大小
      Thread thr = new Thread(Func_NoArguments,262144);
      //啟動(dòng)線程
      thr.Start();
      }
      /// <summary>
      /// Function Of No Arguments.
      /// </summary>
      void Func_NoArguments()
      {
      Debug.Log("Run Func_NoArguments");
      }

    4.線程執(zhí)行有參方法都毒,限制線程要使用的最大堆棧大小

    • 構(gòu)造語(yǔ)法
      /// <summary>
      /// 初始化 Thread 類的新實(shí)例。
      /// </summary>
      /// <param name="start">有參委托對(duì)象.</param>
      /// <param name="maxStackSize">使用的最大堆棧大小.</param>
      public Thread(ParameterizedThreadStart start,int maxStackSize)
      start
      類型:System.Threading.ParameterizedThreadStart
      一個(gè)委托碰缔,它表示此線程開(kāi)始執(zhí)行時(shí)要調(diào)用的方法账劲。
      注意:參數(shù)只能有一個(gè),且必須為object類型
      maxStackSize
      類型:System.Int32
      線程要使用的最大堆棧大薪鹇铡(以字節(jié)為單位)瀑焦;如果為 0,則使用可執(zhí)行文件的文件頭中指定的默認(rèn)最大堆棧大小梗肝。
      重要事項(xiàng):對(duì)于部分受信任的代碼榛瓮,如果 maxStackSize 大于默認(rèn)堆棧大小,則將其忽略巫击。 不引發(fā)異常禀晓。
    • 實(shí)例
      void Start()
      {
      //創(chuàng)建有參線程對(duì)象,限制256KB堆棧大小
      Thread thr = new Thread(Func_Arguments,262144);
      //啟動(dòng)線程,傳入?yún)?shù)
      thr.Start("Lanou");
      }
      /// <summary>
      /// Function Of Have Arguments.
      /// </summary>
      void Func_Arguments(object data)
      {
      Debug.Log("Run Func_Arguments, Data = " + data);
      }
  • 啟動(dòng)線程(上文已使用)

    • 無(wú)參啟動(dòng)
      void Start()
      {
      //創(chuàng)建無(wú)參線程對(duì)象
      Thread thr = new Thread(Func_NoArguments);

//啟動(dòng)線程
thr.Start();

    }
    /// <summary>
    /// Function Of No Arguments.
    /// </summary>
    void Func_NoArguments()
    {
        Debug.Log("Run Func_NoArguments");
    }
  • 有參啟動(dòng)
    void Start()
    {
    //創(chuàng)建有參線程對(duì)象
    Thread thr = new Thread(Func_Arguments);

//啟動(dòng)線程,傳入?yún)?shù)
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)將當(dāng)前線程掛起指定的毫秒數(shù)。
      millisecondsTimeout
      millisecondsTimeout
      類型:System.Int32
      掛起線程的毫秒數(shù)坝锰。 如果 millisecondsTimeout 參數(shù)的值為零,則該線程會(huì)將其時(shí)間片的剩余部分讓給任何已經(jīng)準(zhǔn)備好運(yùn)行的粹懒、有同等優(yōu)先級(jí)的線程。 如果沒(méi)有其他已經(jīng)準(zhǔn)備好運(yùn)行的顷级、具有同等優(yōu)先級(jí)的線程凫乖,則不會(huì)掛起當(dāng)前線程的執(zhí)行。
    • public void Resume()
      繼續(xù)已掛起的線程弓颈。(已過(guò)時(shí))
    • public void Abort()
      在調(diào)用此方法的線程上引發(fā) ThreadAbortException拣凹,以開(kāi)始終止此線程的過(guò)程。 調(diào)用此方法通常會(huì)終止線程恨豁。
    • public void Join()
      阻止調(diào)用線程直到線程終止,同時(shí)繼續(xù)執(zhí)行標(biāo)準(zhǔn)的 COM 和 SendMessage 傳送爬迟。
    • public enum ThreadPriority
      指定 Thread 的調(diào)度優(yōu)先級(jí)橘蜜。
成員名稱 描述
AboveNormal 可以將 Thread 安排在具有 Highest 優(yōu)先級(jí)的線程之后,在具有 Normal 優(yōu)先級(jí)的線程之前。
BelowNormal 可以將 Thread 安排在具有 Normal 優(yōu)先級(jí)的線程之后计福,在具有 Lowest 優(yōu)先級(jí)的線程之前跌捆。
Highest 可以將 Thread 安排在具有任何其他優(yōu)先級(jí)的線程之前。
Lowest 可以將 Thread 安排在具有任何其他優(yōu)先級(jí)的線程之后象颖。
Normal 可以將 Thread 安排在具有 AboveNormal 優(yōu)先級(jí)的線程之后佩厚,在具有 BelowNormal 優(yōu)先級(jí)的線程之前。 默認(rèn)情況下说订,線程具有 Normal 優(yōu)先級(jí)抄瓦。
  • 通過(guò)線程池執(zhí)行線程

    • ThreadPool.QueueUserWorkItem 方法 (WaitCallback)
      public static bool QueueUserWorkItem(WaitCallback callBack)
      callBack
      類型:System.Threading.WaitCallback
      一個(gè) WaitCallback,表示要執(zhí)行的方法陶冷。
      返回值
      類型:System.Boolean
      如果此方法成功排隊(duì)钙姊,則為 true;如果無(wú)法將該工作項(xiàng)排隊(duì)埂伦,則引發(fā) NotSupportedException煞额。
  • Unity使用多線程注意

    1. 變量都是共享的(都能指向相同的內(nèi)存地址)
    2. UnityEngine的API不能在分線程運(yùn)行
    3. UnityEngine定義的基本結(jié)構(gòu)(int,float,Struct定義的數(shù)據(jù)類型)可以在分線程計(jì)算,如 Vector3(Struct)可以 沾谜, 但Texture2d(class,根父類為Object)不可以膊毁。
    4. UnityEngine定義的基本類型的函數(shù)可以在分線程運(yùn)行
  • Unity多線程插件
    LOOM Multi Threading Framework 1.7 下載地址

    LOOM Multi Threading Framework

    • 核心方法
      /// <summary>
      /// Unlike "StartMultithreadedWorkloadExecution", you will have to build your own IThreadWorkerObject.
      /// Downside: It requires some extra work. Upside: you got more controll over what goes in and comes out
      /// Infact: You can create you own polymorphed IThreadWorkerObject-array, each ellement being a completely different type. For example: the statemachines of enemies are IThreadWorkerObject's and the array contains completely different classes with enemies/AI-behaviours.
      /// </summary>
      /// <param name="workerObjects">An array of IThreadWorkerObject objects to be handled by the threads. If you want multiple cores/threads to be active, make sure that the number of IThreadWorkerObject's proves matches/exeeds your preferred number maxWorkingThreads. </param>
      /// <param name="onComplete">Fired when all re-packaged workLoad-objects are finished computing</param>
      /// <param name="onPackageExecuted">Fires foreach finished re-packaged set of workLoad-object</param>
      /// <param name="maxThreads"> Lets you choose how many threads will be run simultaneously by the threadpool. Default: -1 == number of cores minus one, to make sure the MainThread has at least one core to run on. (quadcore == 1 core Mainthread, 3 cores used by the ThreadPoolScheduler)</param>
      /// <param name="scheduler">If Null, a new ThreadPoolScheduler will be instantiated.</param>
      /// <param name="safeMode">Executes all the computations within try-catch events, logging it the message + stacktrace</param>
      /// <returns>A ThreadPoolScheduler that handles all the repackaged workLoad-Objects</returns>
      public static ThreadPoolScheduler StartMultithreadedWorkerObjects(IThreadWorkerObject[] workerObjects, ThreadPoolSchedulerEvent onCompleteCallBack, ThreadedWorkCompleteEvent onPackageExecuted = null, int maxThreads = -1, ThreadPoolScheduler scheduler = null, bool safeMode = true)
      {
      if (scheduler == null)
      scheduler = CreateThreadPoolScheduler();

          scheduler.StartASyncThreads(workerObjects, onCompleteCallBack, onPackageExecuted, maxThreads, safeMode);
          return scheduler;
      }
      

結(jié)束語(yǔ)

Unity可以使用多線程,但對(duì)其有很多限制基跑,所以在不使用UnityEngine API的情況下婚温,可以使用多線程,提高多核CPU的使用率涩僻。通崇哉伲可以將需要大量計(jì)算的算法內(nèi)容,放置到多線程中執(zhí)行逆日,包括邏輯框架也可以放到多線程中執(zhí)行嵌巷。本篇理論性較強(qiáng),后期會(huì)陸續(xù)發(fā)布實(shí)戰(zhàn)型文章室抽。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末搪哪,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子坪圾,更是在濱河造成了極大的恐慌晓折,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件兽泄,死亡現(xiàn)場(chǎng)離奇詭異漓概,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)病梢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門胃珍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)梁肿,“玉大人,你說(shuō)我怎么就攤上這事觅彰》悦铮” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵填抬,是天一觀的道長(zhǎng)烛芬。 經(jīng)常有香客問(wèn)我,道長(zhǎng)飒责,這世上最難降的妖魔是什么赘娄? 我笑而不...
    開(kāi)封第一講書人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮读拆,結(jié)果婚禮上擅憔,老公的妹妹穿的比我還像新娘。我一直安慰自己檐晕,他們只是感情好暑诸,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著辟灰,像睡著了一般个榕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上芥喇,一...
    開(kāi)封第一講書人閱讀 51,462評(píng)論 1 302
  • 那天西采,我揣著相機(jī)與錄音,去河邊找鬼继控。 笑死械馆,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的武通。 我是一名探鬼主播霹崎,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼冶忱!你這毒婦竟也來(lái)了尾菇?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤囚枪,失蹤者是張志新(化名)和其女友劉穎派诬,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體链沼,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡默赂,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了括勺。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片缆八。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡谒臼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出耀里,到底是詐尸還是另有隱情,我是刑警寧澤拾氓,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布冯挎,位于F島的核電站,受9級(jí)特大地震影響咙鞍,放射性物質(zhì)發(fā)生泄漏房官。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一续滋、第九天 我趴在偏房一處隱蔽的房頂上張望翰守。 院中可真熱鬧,春花似錦疲酌、人聲如沸蜡峰。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)湿颅。三九已至,卻和暖如春粥诫,著一層夾襖步出監(jiān)牢的瞬間油航,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工怀浆, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留谊囚,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓执赡,卻偏偏與公主長(zhǎng)得像镰踏,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子搀玖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法余境,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法灌诅,繼承相關(guān)的語(yǔ)法芳来,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,631評(píng)論 18 399
  • 一猜拾、認(rèn)識(shí)多任務(wù)即舌、多進(jìn)程、單線程挎袜、多線程 要認(rèn)識(shí)多線程就要從操作系統(tǒng)的原理說(shuō)起顽聂。 以前古老的DOS操作系統(tǒng)(V 6....
    GT921閱讀 1,013評(píng)論 0 3
  • 線程狀態(tài)新建肥惭,就緒,運(yùn)行紊搪,阻塞蜜葱,死亡。 線程同步多線程可以同時(shí)運(yùn)行多個(gè)任務(wù)耀石,線程需要共享數(shù)據(jù)的時(shí)候牵囤,可能出現(xiàn)數(shù)據(jù)不...
    KevinCool閱讀 804評(píng)論 0 0
  • 一揭鳞、線程的生命周期 線程狀態(tài)轉(zhuǎn)換圖: 1、新建狀態(tài) 用new關(guān)鍵字和Thread類或其子類建立一個(gè)線程對(duì)象后梆奈,該線...
    我是嘻哈大哥閱讀 902評(píng)論 0 8
  • Tips 學(xué)習(xí)算法最好的方法并不是編寫程序野崇,而是手算 千萬(wàn)不要圖快——如果沒(méi)有足夠的時(shí)間來(lái)實(shí)踐,那么學(xué)的快亩钟,忘的也...
    _涼風(fēng)_閱讀 346評(píng)論 0 0