UH4L12——协同程序和异步函数

协同程序和异步函数

之所以需要注册跨域继承适配器,是因为在ILRuntime中的协同程序和异步函数
编译后本质上是通过状态机利用对象的状态来达到的异步,这里面的对象就用到了跨域继承
所以我们需要注册他们的跨域继承适配器来让热更新工程正常使用他们

在ILRuntime热更工程中使用协同程序

如果不注册就直接在热更工程内开启协程,会报错

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class ILRuntimeMain
{
public static void Main()
{
Lesson16 lesson16 = Camera.main.GetComponent<Lesson16>();
lesson16.StartCoroutine(Lesson16Test());
}

public static IEnumerator Lesson16Test()
{
Debug.Log(0);
yield return new WaitForSeconds(1f);
Debug.Log(1);
yield return new WaitForSeconds(1f);
Debug.Log(2);
yield return new WaitForSeconds(1f);
Debug.Log(3);
}
}

image

需要注册 协同程序的 跨域继承适配器,可以在示例工程中获取

image

然后,在appDomain加载完dll和pdb文件后的初始化逻辑中加上对CoroutineAdapter​的跨域继承注册

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private unsafe void InitILRuntime()
{
//注册委托和委托转换器...
//注册跨域继承类
appDomain.RegisterCrossBindingAdaptor(new ILRuntimeAdapter.Lesson11_TestAdapter());
appDomain.RegisterCrossBindingAdaptor(new CoroutineAdapter());
//注册值类型
appDomain.RegisterValueTypeBinder(typeof(Vector3), new Vector3Binder());
appDomain.RegisterValueTypeBinder(typeof(Vector2), new Vector2Binder());
appDomain.RegisterValueTypeBinder(typeof(Quaternion), new QuaternionBinder());

//CLR重定向内容,必须要写到CLR绑定之前!!!
System.Type debugType = typeof(Debug);
MethodInfo methodInfo = debugType.GetMethod("Log", new System.Type[] { typeof(object) });
appDomain.RegisterCLRMethodRedirection(methodInfo, MyLog);

//注册 CLR绑定相关信息
ILRuntime.Runtime.Generated.CLRBindings.Initialize(appDomain);
//初始化ILRuntime相关信息(目前只需要告诉ILRuntime主线程的线程ID,主要目的是能够在Unity的Profiler剖析器窗口中分析问题)
appDomain.UnityMainThreadID = Thread.CurrentThread.ManagedThreadId;
}

输出:image

在ILRuntime热更工程中使用异步函数

注册 异步函数的 跨域继承适配器,可以获取别人写好的异步函数跨域适配器:

jumpst.github.io/IAsyncStateMachineClassInheritanceAdaptor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
using System;
using ILRuntime.CLR.Method;
using ILRuntime.Runtime.Enviorment;
using ILRuntime.Runtime.Intepreter;

namespace ILRuntimeTest.TestFramework
{
public class IAsyncStateMachineClassInheritanceAdaptor : CrossBindingAdaptor
{
public override Type BaseCLRType
{
get
{
return typeof(System.Runtime.CompilerServices.IAsyncStateMachine);
}
}

public override Type AdaptorType
{
get
{
return typeof(IAsyncStateMachineAdaptor);
}
}

public override object CreateCLRInstance(ILRuntime.Runtime.Enviorment.AppDomain appdomain, ILTypeInstance instance)
{
return new IAsyncStateMachineAdaptor(appdomain, instance);
}

public class IAsyncStateMachineAdaptor : System.Runtime.CompilerServices.IAsyncStateMachine, CrossBindingAdaptorType
{
ILTypeInstance instance;
ILRuntime.Runtime.Enviorment.AppDomain appdomain;
CrossBindingMethodInfo mMoveNext_0 = new CrossBindingMethodInfo("MoveNext");
CrossBindingMethodInfo<System.Runtime.CompilerServices.IAsyncStateMachine> mSetStateMachine_1 = new CrossBindingMethodInfo<System.Runtime.CompilerServices.IAsyncStateMachine>("SetStateMachine");

public IAsyncStateMachineAdaptor()
{

}

public IAsyncStateMachineAdaptor(ILRuntime.Runtime.Enviorment.AppDomain appdomain, ILTypeInstance instance)
{
this.appdomain = appdomain;
this.instance = instance;
}

public ILTypeInstance ILInstance { get { return instance; } }

public void MoveNext()
{
mMoveNext_0.Invoke(this.instance);
}

public void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine stateMachine)
{
mSetStateMachine_1.Invoke(this.instance, stateMachine);
}

public override string ToString()
{
IMethod m = appdomain.ObjectType.GetMethod("ToString", 0);
m = instance.Type.GetVirtualMethod(m);
if (m == null || m is ILMethod)
{
return instance.ToString();
}
else
return instance.Type.FullName;
}
}
}
}

在热更工程内执行异步方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class ILRuntimeMain
{
public static void Main()
{
Lesson16Test2();
}

public static async void Lesson16Test2()
{
Debug.Log(0);
await Task.Delay(1000);
Debug.Log(1);
await Task.Delay(1000);
Debug.Log(2);
await Task.Delay(1000);
Debug.Log(3);
}
}

如果不提前注册,直接调用同样会报错,因此同样需要在appDomain​加载完dll和pdb文件后的初始化逻辑中
加上对IAsyncStateMachineClassInheritanceAdaptor​的跨域继承注册

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private unsafe void InitILRuntime()
{
//注册委托和委托转换器
//注册跨域继承类
appDomain.RegisterCrossBindingAdaptor(new ILRuntimeAdapter.Lesson11_TestAdapter());
appDomain.RegisterCrossBindingAdaptor(new CoroutineAdapter());
appDomain.RegisterCrossBindingAdaptor(new IAsyncStateMachineClassInheritanceAdaptor());
//注册值类型
appDomain.RegisterValueTypeBinder(typeof(Vector3), new Vector3Binder());
appDomain.RegisterValueTypeBinder(typeof(Vector2), new Vector2Binder());
appDomain.RegisterValueTypeBinder(typeof(Quaternion), new QuaternionBinder());


//CLR重定向内容,必须要写到CLR绑定之前!!!
System.Type debugType = typeof(Debug);
MethodInfo methodInfo = debugType.GetMethod("Log", new System.Type[] { typeof(object) });
appDomain.RegisterCLRMethodRedirection(methodInfo, MyLog);

//注册 CLR绑定相关信息
ILRuntime.Runtime.Generated.CLRBindings.Initialize(appDomain);
//初始化ILRuntime相关信息(目前只需要告诉ILRuntime主线程的线程ID,主要目的是能够在Unity的Profiler剖析器窗口中分析问题)
appDomain.UnityMainThreadID = Thread.CurrentThread.ManagedThreadId;
}

输出:image