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"]);
}
}
}
本系列文章导读:
- Unity热更新方案C#Like(一)-序言
- Unity热更新方案C#Like(二)-导出官方示范的例子,确认方案可行性
- Unity热更新方案C#Like(三)-详解支持的C#特性:类
- Unity热更新方案C#Like(四)-详解支持的C#特性:委托和Lambda
- Unity热更新方案C#Like(五)-详解支持的C#特性:运算表达式
- Unity热更新方案C#Like(六)-详解支持的C#特性:循环语法
- Unity热更新方案C#Like(七)-详解支持的C#特性:get/set访问器
- Unity热更新方案C#Like(八)-详解支持的C#特性:多线程
- Unity热更新方案C#Like(九)-详解支持的C#特性:Using和命名空间
- Unity热更新方案C#Like(十)-详解支持的C#特性:宏和区域
- Unity热更新方案C#Like(十一)-详解支持的C#特性:枚举
- Unity热更新方案C#Like(十二-详解支持的C#特性:参数修饰符
- Unity热更新方案C#Like(十三)-详解支持的C#特性:函数重载和默认参数
- Unity热更新方案C#Like(十四)-详解支持的C#特性:异常处理
- Unity热更新方案C#Like(十五)-详解支持的C#特性:关键字:unsafe typeof nameof $ @ #pragma #warning #error
- Unity热更新方案C#Like(十六)-详解支持的C#特性:其他杂项:初始值设定项,表达式主体,内联变量声明
- Unity热更新方案C#Like(十七)-详解支持的长链接Socket和WebSocket
- Unity热更新方案C#Like(十八)-详解如何和Unity交互
- Unity热更新方案C#Like(十九)-详解KissJSON:唯一可以在本热更新框架使用的JSON库
- Unity热更新方案C#Like(二十)-详解KissCSV:一个简易实用的CSV表格读取方式
- Unity热更新方案C#Like(廿一)-详解KissFrameworkServer:对应的示范例子和官网所用的服务器框架
- Unity热更新方案C#Like(廿二)-详解内置的例子C#Like Demo:飞机大战,简易聊天室,简易账号/物品/邮件系统
- Unity热更新方案C#Like(廿三)-实战:示范如何把Unity官方免费例子Tanks! Tutorial转成可热更新项目
- Unity热更新方案C#Like(廿四)-实战:示范如何把Unity官方免费例子Platformer Microgame转成可热更新项目
- Unity热更新方案C#Like(廿五)-实战:示范如何建立初始包CSharpLikeFreeDemo项目
- Unity热更新方案C#Like(廿六)-(可选)详解免费版的演示如何升级到完整版的演示