没看过前两篇的客官请移步
Unity主线程和子线程交叉调用(一)
Unity主线程和子线程交叉调用(二)
-
延伸一 我们完全可以略加修改,并把这篇文章修改为"多线程下的交叉调用"。所谓的回到主线程就是回到某个子线程。但是实际项目中光是这样的代码还是不行的。因为这种设计,线程一旦复杂,维护起来就是个问题。
-
延伸二 一伸二,二伸三,三伸万物。我们的终极目标应该是多线程下的编程模式。我在查资料的时候发现,Loom这种有点像加瓦同学可能耳熟能详的 “Active Object”模式。它是一种异步的编程模式,将调用和执行进行分离。什么意思呢,就是这头呢我调用了我自己编写的方法,但是这个方法真正执行的地方并不是在这也不是在此时。 Active Object有几个基本要素,结合我们自己的实现可以对号入座 Proxy:负责对外暴露异步方法接口
//发起一个线程,执行一段异步任务 EditorLoom.RunOnAsync(MainFun1);
MethodRequest:负责将客户端代码对Proxy实例的异步方法的调用封装为一个对象
//主线程任务生成的对象
public
struct
MainThreadTask
{
//何时运行该函数
public
System
.
DateTime
time
;
public
Action
action
;
}
Schedule:MethodRequest实例存入的一个维护列表,按调度策略执行。我们的策略是时间排序和顺序排序
private List<MainThreadTask> allDelayed = new List<MainThreadTask>();
当然我们并不是完全遵循Active Object的,甚至相差巨大。想进一步了解Active Object具体思想,可以访问文末链接
-
异常问题 我曾经遇到过子线程下的异常没用正常抛出的情况,就是输出框不会把异常信息打印出来,这是非常危险的。现在使用2017版本的Unity我还没遇到过这种问题。当时我的解决方案贴出来给大家看一下 1,善用try catch 2, 主动捕获异常
void
Start
(
)
{
//当应用程序域某个异常未被捕获时会触发事件“UnhandledException”
AppDomain
app
=
AppDomain
.
CurrentDomain
;
app
.
UnhandledException
+=
App1_UnhandledException
;
}
private
void
App1_UnhandledException
(
object
sender
,
UnhandledExceptionEventArgs
e
)
{
Debug
.
Log
(
e
.
ExceptionObject
.
ToString
(
)
)
;
}
-
弊端 技术不够成熟的情况下,我建议仅仅在特殊的场合,万不得已的情况下才使用这种多线程方案。况且用协程可以解决90%的问题,基本可以代替线程。主要是因为 1,引擎是主循环结构,逻辑更新和画面更新要确定和一致。加入线程会导致同步问题,难以维护 2,代码编写不过关,会带来线程安全和锁的问题 3,确定性能瓶颈才是重中之重,建议优先使用其他方案优化。有时候多线程优化的效果并不会太明显,盲目启动大量线程反而会带来线程上下文切换性能问题 4,程序结构不好设计。
参考文章:
Active Object(主动对象)模式
本文探讨了Unity中主线程与子线程的交叉调用,介绍了如何利用类似ActiveObject模式的Loom来实现异步编程,讨论了线程安全、异常处理及多线程在Unity项目中的应用挑战。

被折叠的 条评论
为什么被折叠?



