Unity3D中的多線程新體驗(yàn)-Timer

前面些時(shí)候要研究串口通訊陡鹃,于是就接觸到了多線程方妖,期間呢分扎,筆者想當(dāng)然的把在線程里面使用了Unity 的 Text。然后就報(bào)錯(cuò)鲜棠,然后呢就遇見了 Loom,嗯培慌,設(shè)計(jì)的很巧妙豁陆,蠻好吃的!
所以吵护,我就把自家曾經(jīng)寫的 Timer,重構(gòu)了下献联,于是就有了本文,下面進(jìn)入正題:

異常&解決方案

非主線程不能調(diào)用

Loom 提供的解決方案
Timer 提供的解決方案

Loom的設(shè)計(jì)

就是把操作Unity組件的邏輯塊使用 Action 包裹埋入到非主線程的上下文何址,但這個(gè)線程執(zhí)行到這個(gè)位置就把這些個(gè) Action 拋入MonoBehaviour的 Update中執(zhí)行他 里逆,實(shí)現(xiàn)的效果如下:

  1. 更優(yōu)的代碼的可讀性和邏輯連續(xù)性
  2. 更小范圍的數(shù)據(jù)可見性(閉包優(yōu)勢)
  3. 實(shí)時(shí)與 Unity 組件交互(閉包優(yōu)勢)

Timer的設(shè)計(jì)

只因?yàn)槎嗫戳艘谎郏虐l(fā)現(xiàn) Timer 的 TimerDriver 理念 原來跟這個(gè) Loom 是那么的相近:
都是利用委托Action 把邏輯塊插入其他邏輯塊的上下文用爪,然后利用閉包的優(yōu)勢共享這個(gè)被插邏輯塊上下文的局部變量原押。
然后其實(shí)呢,執(zhí)行這個(gè) Action 的是另一個(gè)繼承了MonoBehaviour 的類偎血,在Timer中 我謂之:TimerDirver诸衔。

小結(jié)

綜上盯漂,這個(gè)Loom 帶來的 Unity多線程 炫酷體驗(yàn),只需要簡單的重構(gòu)笨农,俺家的 Tiemr 也必定兼并你的特色功能就缆,下面就是重構(gòu)大體思路

重構(gòu) Timer

  1. 剔除Timer 中 UnityEgine 相關(guān)的API : Time.realtimeSinceStartup 、Time.time谒亦。
  2. 將上述剔除的 CurrentTime 實(shí)際驅(qū)動(dòng) 放到 TimerDriver Update中竭宰。
  3. 為線程安全,對定時(shí)器鏈表 List<Timer> timers 各處上鎖。
  4. 如果在非主線程中TimerDriver初始化會(huì)報(bào)錯(cuò)份招,新增 Timer.IntializeDriver()切揭,提供手動(dòng)初始化TimerDriver 的能力,在主線程初始化不會(huì)這樣麻煩锁摔。

應(yīng)用場景1-簡單的應(yīng)用

using UnityEngine;
using System.Threading.Tasks;
using QFramework.TimeExtend;
using Timer = QFramework.TimeExtend.Timer;
using UnityEngine.UI;

public class TestForTimer : MonoBehaviour
{
    public Text text;
    private void Awake()
    {
        Timer.IntializeDriver(); //首次初始化不能放在非主線程內(nèi)廓旬。
    }
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.R))
        {
            this.FunctionA();
        }
    }
    internal void FunctionA()
    {
        Task task = new Task(() =>
        {
            string _name = "CreateWithTimer ←";
            Timer.AddTimer(0).OnCompleted(() =>
            {
                text.text = _name;  //先演示異常
                new GameObject(_name);
            });
        });
        task.Start();
    }
}


動(dòng)畫演示


Tips:
先嘗試在 Task 內(nèi)直接更新 Text組件數(shù)據(jù) ,失斝逞孕豹!
再嘗試 Timer 內(nèi)運(yùn)行,完美解決報(bào)錯(cuò)十气!

應(yīng)用場景2 - Http下載

參考:Unity技術(shù)博客 - 客戶端斷點(diǎn)續(xù)傳 - 簡書

using UnityEngine;
using Timer = QFramework.TimeExtend.Timer;
using System;
using System.IO;
using UnityEngine.UI;

public class TestDownload : MonoBehaviour
{
    public string url = "http://localhost:8083/bigFile";
    public string savePath = "";
    public Text finish;
    public Text update;

    HttpDownLoader DownLoader;
    void Awake()
    {
        savePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "TestDownLoad");
        Timer.IntializeDriver();
        Loom.Initialize();
        DownLoader = new HttpDownLoader();
        DownLoader.OnDownLoadCompleted.AddListener(() =>
        {
            this.finish.text = "下載完成励背!";
        });
        DownLoader.OnDownLoadUpdate.AddListener(v =>
        {
            this.update.text = string.Format("下載進(jìn)度:{0} %", (v * 100).ToString("f2"));
        });
    }
    private void Start()
    {
        this.DownLoader.DownLoad(url, savePath);
    }
    private void OnDisable()
    {
        this.DownLoader.Close();
    }
}

動(dòng)畫演示


使用 Timer 埋入 Update 事件更新下載進(jìn)度

Tips:
使用 Timer 或者 Loom 將 OnComplete 和OnUpdate 回調(diào)埋進(jìn)去,實(shí)現(xiàn)事件驅(qū)動(dòng)的進(jìn)度刷新和下載完成提示桦踊,無需額外的判斷椅野。

擴(kuò)展閱讀

  1. Unity多線程(Thread)和主線程(MainThread)交互使用類——Loom工具分享
  2. 重構(gòu)后的 Timer -GitHub
  3. Unity技術(shù)博客 - 客戶端斷點(diǎn)續(xù)傳 - 簡書

Unity非主進(jìn)程內(nèi)訪問Unity組件報(bào)錯(cuò)、怎么在其他進(jìn)程直接操作Unity組件籍胯、Unity多線程
可以做為 Loom 插件的課外知識竟闪,但不保證這個(gè)Timer 能夠合理的處理高并發(fā),畢竟筆者是個(gè)菜雞兒杖狼,尤其是多線程編程炼蛤。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蝶涩,隨后出現(xiàn)的幾起案子理朋,更是在濱河造成了極大的恐慌,老刑警劉巖绿聘,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嗽上,死亡現(xiàn)場離奇詭異,居然都是意外死亡熄攘,警方通過查閱死者的電腦和手機(jī)兽愤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人浅萧,你說我怎么就攤上這事逐沙。” “怎么了洼畅?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵吩案,是天一觀的道長。 經(jīng)常有香客問我帝簇,道長徘郭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任己儒,我火速辦了婚禮崎岂,結(jié)果婚禮上捆毫,老公的妹妹穿的比我還像新娘闪湾。我一直安慰自己,他們只是感情好绩卤,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布途样。 她就那樣靜靜地躺著,像睡著了一般濒憋。 火紅的嫁衣襯著肌膚如雪何暇。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天凛驮,我揣著相機(jī)與錄音裆站,去河邊找鬼。 笑死黔夭,一個(gè)胖子當(dāng)著我的面吹牛宏胯,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播本姥,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼肩袍,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了婚惫?” 一聲冷哼從身側(cè)響起氛赐,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎先舷,沒想到半個(gè)月后艰管,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蒋川,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年牲芋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,015評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡街图,死狀恐怖浇衬,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情餐济,我是刑警寧澤耘擂,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站絮姆,受9級特大地震影響醉冤,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜篙悯,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一蚁阳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鸽照,春花似錦螺捐、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至诞外,卻和暖如春澜沟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背峡谊。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工茫虽, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人既们。 一個(gè)月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓濒析,卻偏偏與公主長得像,于是被迫代替她去往敵國和親贤壁。 傳聞我的和親對象是個(gè)殘疾皇子悼枢,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,969評論 2 355

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