Unity热更新方案C#Like(八)-详解支持的C#特性:多线程

C#Like是Unity的热更方案,使用纯C#语言写出可以热更新的代码,就像可以在所有平台使用DLL(动态链接库)文件一样.遵从KISS设计原则,让用户轻松构建或升级成Unity的热更新项目.

简介

本篇主要介绍C#Like支持的C#特性:多线程.

  • C#Like免费版:支持多线程 
  • C#Like完整版:多了lock语法
  • 两者在WebGL平台下均不支持多线程

C#Like免费版:

示范代码如下:

using System;  
using System.Collections.Generic;  
using System.Threading;  
using UnityEngine;  
using UnityEngine.UI;  
using Random = UnityEngine.Random;  
  
namespace CSharpLike  
{  
    public partial class ExampleCSharp : LikeBehaviour  
    {  
        void TestThread()  
        {  
            Debug.LogError("示范多线程: 你不能在C#Like免费版里使用'lock'语句(在完整版已支持).强烈推荐升级到完整版:");  
            // 我们提供以下方案给免费用户:  
            // 'lock'语句: 在非热更代码里使用,或者不用(可能引起多线程安全问题)  
  
            //最易用的调起无参数的多线程函数方式  
            HotUpdateManager.CreateThread(TestThreadRunLoop);  
  
            //测试Task.Run  
            Task.Run(() =>  
            {  
                Debug.LogError("Task.Run as lambda start " + DateTime.Now);  
                Thread.Sleep(2000);  
                Debug.LogError("Task.Run as lambda end " + DateTime.Now);  
            });  
            Task.Run(TestTaskRun);  
        }  
        void TestTaskRun()  
        {  
            Debug.LogError("Task.Run as delegate start " + DateTime.Now);  
            Thread.Sleep(4000);  
            Debug.LogError("Task.Run as delegate end " + DateTime.Now);  
        }  
        /// <summary>  
        /// "Test C#"按钮进去后的按钮"TestThread"的预制体里绑定的按钮响应函数  
        /// </summary>  
        void OnClickTestThread()  
        {  
            GetComponent<Text>("TestMessage").text = "OnClickTestThread";  
            //最易用的调起带参数的多线程函数方式  
            JSONData jsonData = JSONData.NewDictionary();  
            jsonData["id"] = Random.Range(1, 1000);  
            jsonData["data"] = JSONData.NewList();  
            jsonData["data"].Add("dump1");  
            jsonData["data"].Add("dump2");  
            List<int> testParams = new List<int>();//传入List<int>类型的参数  
            testParams.Add(123);  
            jsonData.SetObjectExtern("TestExternMsg", testParams);//Set extern params to thread  
            HotUpdateManager.CreateThread(DoSomeWorkInThread,//这个是带参数的函数名  
                jsonData,//这个是传递给函数的参数  
                behaviour,//这个是当前HotUpdateBehaviour组件,如果无需回调给unity主线程处理则无需传入  
                OnDoSomeWorkInThreadDone);//这个是回调给unity主线程处理的函数名,如果不需要则无需传入  
  
            //这里修改一个数值,让前面开启的多线程打印一个log  
            countInThread = Random.Range(1, 1000);  
  
        }  
        bool bExist = false;  
        void OnDestroy()  
        {  
            bExist = true;//退出时候通知前面开启的多线程退出  
        }  
        object objLock = new object();  
        int countInThread = 0;  
        volatile int countLoopThread = 0;//测试关键字 'volatile'   
        /// <summary>  
        /// 不带参数的多线程函数  
        /// </summary>  
        void TestThreadRunLoop()  
        {  
            Debug.LogError("TestThreadRunLoop start");  
            while (!bExist)//直到组件销毁才退出  
            {  
                if (countInThread > 0)  
                {  
                    Debug.LogError("TestThreadRunLoop:countInThread=" + countInThread);  
                    countInThread = 0;  
                }  
                if ((++countLoopThread) >= 10000)  
                    countLoopThread = 0;  
                Thread.Sleep(200);//休眠0.2秒  
            }  
            Debug.LogError("TestThreadRunLoop end");   
        }  
        /// <summary>  
        /// 带参数的多线程函数  
        /// </summary>  
        void DoSomeWorkInThread(object obj)  
        {  
            //我们通过'JSONData'来传递参数.传回Unity主线程的计算结果也是用这个.  
            //可以在里面传递数据  
            JSONData jsonData = obj as JSONData;  
  
            List<int> testParams = jsonData.GetObjectExtern("TestExternMsg") as List<int>;//test extern param  
            Debug.Log("DoSomeWorkInThread testParams.Count=" + testParams.Count);  
            //这里示范在多线程内做一些工作 (你不能在本线程访问Unity的组件,例如'PlayerPrefs', 和原生C#代码一样.)  
            Debug.Log("DoSomeWorkInThread(" + jsonData + ") start at " + DateTime.Now);  
            long count = 0;  
            int id = jsonData["id"];  
            for (int i = 0; i < 10000; i++)  
            {  
                id += jsonData.Count;//不要直接使用'jsonData["id"] += jsonData.Count;',因为JSONData在热更新代码中不是那么高效,在这循环10000次的循环内要花太多时间了  
                Interlocked.Increment(ref count);  
            }  
            jsonData["id"] = id;  
            Debug.Log("DoSomeWorkInThread(" + jsonData + ") end at " + DateTime.Now);  
  
            //通知主线程,我干完活了  
            HotUpdateManager.OnThreadDone(jsonData);//标识为多线程完成了(我们会自动在里面通知主线程执行预先设定的回调函数)  
        }  
        /// <summary>  
        /// 当多线程工作完成后在主线程刷新UI  
        /// </summary>  
        void OnDoSomeWorkInThreadDone(object obj)  
        {  
            JSONData jsonData = obj as JSONData;  
            GetComponent<Text>("TestMessage").text = "OnDoSomeWorkInThreadDone:"+ jsonData["id"];//显示在多线程计算的结果  
            Debug.Log("OnDoSomeWorkInThreadDone:" + jsonData["id"]);  
        }  
    }  
}

 C#Like完整版:

示范代码如下:

using System;  
using System.Collections.Generic;  
using System.Threading;  
using UnityEngine;  
using UnityEngine.UI;  
using Random = UnityEngine.Random;  
  
namespace CSharpLike  
{  
    public partial class ExampleCSharp : LikeBehaviour  
    {  
        void TestThread()  
        {  
            Debug.LogError("测试多线程:");  
            //最易用的调起无参数的多线程函数方式  
            HotUpdateManager.CreateThread(TestThreadRunLoop);  
  
            //测试Task.Run  
            Task.Run(() =>  
            {  
                Debug.LogError("Task.Run as lambda start " + DateTime.Now);  
                Thread.Sleep(2000);  
                Debug.LogError("Task.Run as lambda end " + DateTime.Now);  
            });  
            Task.Run(TestTaskRun);  
        }  
        void TestTaskRun()  
        {  
            Debug.LogError("Task.Run as delegate start " + DateTime.Now);  
            Thread.Sleep(4000);  
            Debug.LogError("Task.Run as delegate end " + DateTime.Now);  
        }  
        /// <summary>  
        /// "Test C#"按钮进去后的按钮"TestThread"的预制体里绑定的按钮响应函数   
        /// </summary>  
        void OnClickTestThread()  
        {  
            GetComponent<Text>("TestMessage").text = "OnClickTestThread";  
            //最易用的调起带参数的多线程函数方式  
            JSONData jsonData = JSONData.NewDictionary();  
            jsonData["id"] = Random.Range(1, 1000);  
            jsonData["data"] = JSONData.NewList();  
            jsonData["data"].Add("dump1");  
            jsonData["data"].Add("dump2");  
            List<int> testParams = new List<int>();//传入List<int>类型的参数  
            testParams.Add(123);  
            jsonData.SetObjectExtern("TestExternMsg", testParams);//Set extern params to thread  
            HotUpdateManager.CreateThread(DoSomeWorkInThread,//这个是带参数的函数名  
                jsonData,//这个是传递给函数的参数  
                behaviour,//这个是当前HotUpdateBehaviour组件,如果无需回调给unity主线程处理则无需传入  
                OnDoSomeWorkInThreadDone);//这个是回调给unity主线程处理的函数名,如果不需要则无需传入  
  
            //这里修改一个数值,让前面开启的多线程打印一个log  
            countInThread = Random.Range(1, 1000);  
  
        }  
        bool bExist = false;  
        void OnDestroy()  
        {  
            bExist = true;//退出时候通知前面开启的多线程退出  
        }  
        object objLock = new object();  
        int countInThread = 0;  
        volatile int countLoopThread = 0;//测试关键字 'volatile'   
        /// <summary>  
        /// 不带参数的多线程函数  
        /// </summary>  
        void TestThreadRunLoop()  
        {  
            Debug.LogError("TestThreadRunLoop start");  
            while (!bExist)//直到组件销毁才退出  
            {  
                lock (objLock)//你可以通过lock关键字来保护线程安全  
                {  
                    if (countInThread > 0)  
                    {  
                        Debug.LogError("TestThreadRunLoop:countInThread=" + countInThread);  
                        countInThread = 0;  
                    }  
                }  
                if ((++countLoopThread) >= 10000)  
                    countLoopThread = 0;  
                Thread.Sleep(200);//休眠0.2秒  
            }  
            Debug.LogError("TestThreadRunLoop end");   
        }  
        /// <summary>  
        /// 带参数的多线程函数  
        /// </summary>  
        void DoSomeWorkInThread(object obj)  
        {  
            //我们通过'JSONData'来传递参数.传回Unity主线程的计算结果也是用这个.  
            //可以在里面传递数据  
            JSONData jsonData = obj as JSONData;  
  
            List<int> testParams = jsonData.GetObjectExtern("TestExternMsg") as List<int>;//test extern param  
            Debug.Log("DoSomeWorkInThread testParams.Count=" + testParams.Count);  
            //这里示范在多线程内做一些工作 (你不能在本线程访问Unity的组件,例如'PlayerPrefs', 和原生C#代码一样.)  
            Debug.Log("DoSomeWorkInThread(" + jsonData + ") start at " + DateTime.Now);  
            long count = 0;  
            int id = jsonData["id"];  
            for (int i = 0; i < 10000; i++)  
            {  
                id += jsonData.Count;//不要直接使用'jsonData["id"] += jsonData.Count;',因为JSONData在热更新代码中不是那么高效,在这循环10000次的循环内要花太多时间了  
                Interlocked.Increment(ref count);  
            }  
            jsonData["id"] = id;  
            Debug.Log("DoSomeWorkInThread(" + jsonData + ") end at " + DateTime.Now);  
  
            //通知主线程,我干完活了  
            HotUpdateManager.OnThreadDone(jsonData);//标识为多线程完成了(我们会自动在里面通知主线程执行预先设定的回调函数)  
        }  
        /// <summary>  
        /// 当多线程工作完成后在主线程刷新UI  
        /// </summary>  
        void OnDoSomeWorkInThreadDone(object obj)  
        {  
            JSONData jsonData = obj as JSONData;  
            GetComponent<Text>("TestMessage").text = "OnDoSomeWorkInThreadDone:"+ jsonData["id"];//显示在多线程计算的结果  
            Debug.Log("OnDoSomeWorkInThreadDone:" + jsonData["id"]);  
        }  
    }  
} 

 本系列文章导读:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C#Like

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

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值