Unity子线程与主线程交互(委托方式)

Unity  Api无法从子线程访问, 但有些操作(例:IO存取文件)又必须子线程运行, 故实现在子线程做耗时操作, 完成后通知主线程更新状态

事件监听方式, 规避回调地狱:https://blog.csdn.net/qq_34987964/article/details/107318813

using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;

/// <summary>
/// 子线程与主线程交互(委托实现)
/// </summary>
public class Loom : MonoBehaviour
{
    private static Loom _instance = null;
    //单例模式(此方法只能在主线程调用)
    public static void Instance()
    {
        if (_instance == null)
        {
            var obj = new GameObject("Loom");
            XLuaManager.DontDestroyOnLoad(obj);
            obj.AddComponent<Loom>();
        }
    }

    //委托队列
    private Queue<Action> asyncQueue = new Queue<Action>();
    private Queue<Action> mainQueue = new Queue<Action>();
    //线程对象
    private Thread thread = null;

    //主线程每次Update执行Function数量
    private static int doUpdate = 5;

    void Awake()
    {
        if (_instance != null)
        {
            DestroyImmediate(gameObject);
            return;
        }
        _instance = this;
        ThreadStart();
    }
    void Update()
    {
        DoFunction();
    }

    //执行Action(根据线程判断对应的方法)
    private void DoFunction()
    {
        if (Thread.CurrentThread == thread)
        {
            if (asyncQueue.Count > 0)
            {
                var func = asyncQueue.Dequeue();
                func();
            }
        }
        else
        {
            if (mainQueue.Count > 0)
            {
                int number = doUpdate;
                do
                {
                    var func = mainQueue.Dequeue();
                    func();
                    number--;
                } while (number > 0 && mainQueue.Count > 0);
            }
        }
    }
    public void AsyncFunction(Action action)
    {
        asyncQueue.Enqueue(action);
    }
    public void MainFunction(Action action)
    {
        mainQueue.Enqueue(action);
    }
    //停止线程
    public void ThreadStop()
    {
        if (thread != null && thread.IsAlive)
        {
            thread.Abort();
            thread = null;
            DestroyImmediate(gameObject);
        }
    }
    void ThreadStart()
    {
        ThreadStop();
        thread = new Thread(new ThreadStart(ThreadDelegate));
        thread.IsBackground = true;
        thread.Start();
    }
    void ThreadDelegate()
    {
        while (this != null)
        {
            DoFunction();
        }
        Debug.Log("Thread Done");
    }
    void OnDestroy()
    {
        Dispose();
    }

    public static void InvokeAsync(Action action)
    {
        if (_instance == null)
        {
            throw new Exception("未实例化Loom对象");
        }
        lock (_instance)
        {
            _instance.AsyncFunction(action);
        }

    }
    public static void InvokeMain(Action action)
    {
        if (_instance == null)
        {
            throw new Exception("未实例化Loom对象");
        }
        lock (_instance)
        {
            _instance.MainFunction(action);
        }
    }
    public static bool IsAlive()
    {
        if (_instance != null)
        {
            lock (_instance)
            {
                return _instance.asyncQueue.Count > 0 || _instance.mainQueue.Count > 0;
            }
        }
        return false;
    }
    public static void Dispose()
    {
        if (_instance != null)
        {
            lock (_instance)
            {
                _instance.asyncQueue.Clear();
                _instance.mainQueue.Clear();
                _instance.ThreadStop();
                Destroy(_instance.gameObject);
                _instance = null;
            }
        }
    }
}

 

  • 1
    点赞
  • 9
    收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论 2

打赏作者

夢暁de光

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值